summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2010-02-18 10:58:03 (GMT)
committerSamuel Rødal <sroedal@trolltech.com>2010-02-18 12:48:56 (GMT)
commit37d4bde65a28a10efdd9c09b88007acd7339629a (patch)
treec6b502994ab7c754a591f667d8212d33a72c8ebc
parent5cd93666050076053d547d1b3ba4041b8fae58ec (diff)
downloadQt-37d4bde65a28a10efdd9c09b88007acd7339629a.zip
Qt-37d4bde65a28a10efdd9c09b88007acd7339629a.tar.gz
Qt-37d4bde65a28a10efdd9c09b88007acd7339629a.tar.bz2
Reduced the memory footprint of qttrace files.
A couple of improvements have been made: * Use single precision floats for the traces. * Reduce the number of variant wrapped transforms by introducing a new translate command. * Reduce the number of bytes streamed per image / pixmap draw command. * Add versioning info to qttrace files to be more future proof. Reviewed-by: Gunnar Sletta
-rw-r--r--src/gui/painting/qpaintbuffer.cpp114
-rw-r--r--src/gui/painting/qpaintbuffer_p.h1
-rw-r--r--src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp9
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp10
-rw-r--r--tools/qttracereplay/main.cpp12
5 files changed, 131 insertions, 15 deletions
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index 664d864..39b76c8 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -308,6 +308,8 @@ public:
Q_Q(QPaintBufferEngine);
q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
}
+
+ QTransform last;
};
@@ -494,6 +496,32 @@ void QPaintBufferEngine::renderHintsChanged()
void QPaintBufferEngine::transformChanged()
{
+ Q_D(QPaintBufferEngine);
+ const QTransform &transform = state()->matrix;
+
+ QTransform delta;
+
+ bool invertible = false;
+ if (transform.type() <= QTransform::TxScale && transform.type() == d->last.type())
+ delta = transform * d->last.inverted(&invertible);
+
+ d->last = transform;
+
+ if (invertible && delta.type() == QTransform::TxNone)
+ return;
+
+ if (invertible && delta.type() == QTransform::TxTranslate) {
+#ifdef QPAINTBUFFER_DEBUG_DRAW
+ qDebug() << "QPaintBufferEngine: transformChanged (translate only) " << state()->matrix;
+#endif
+ QPaintBufferCommand *cmd =
+ buffer->addCommand(QPaintBufferPrivate::Cmd_Translate);
+
+ qreal data[] = { delta.dx(), delta.dy() };
+ cmd->extra = buffer->addData((qreal *) data, 2);
+ return;
+ }
+
// ### accumulate, like in QBrush case...
if (!buffer->commands.isEmpty()
&& buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
@@ -1013,6 +1041,7 @@ void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
void QPaintBufferEngine::setState(QPainterState *s)
{
+ Q_D(QPaintBufferEngine);
if (m_begin_detected) {
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
@@ -1031,6 +1060,8 @@ void QPaintBufferEngine::setState(QPainterState *s)
buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
}
+ d->last = s->matrix;
+
QPaintEngineEx::setState(s);
}
@@ -1152,6 +1183,15 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
painter->setTransform(xform * m_world_matrix);
break; }
+ case QPaintBufferPrivate::Cmd_Translate: {
+ QPointF delta(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
+#ifdef QPAINTBUFFER_DEBUG_DRAW
+ qDebug() << " -> Cmd_Translate, offset: " << cmd.offset << delta;
+#endif
+ painter->translate(delta.x(), delta.y());
+ return;
+ }
+
case QPaintBufferPrivate::Cmd_SetCompositionMode: {
QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
#ifdef QPAINTBUFFER_DEBUG_DRAW
@@ -1797,8 +1837,28 @@ struct QPaintBufferCacheEntry
QVariant::Type type;
quint64 cacheKey;
};
+
+struct QPaintBufferCacheEntryV2
+{
+ enum Type {
+ ImageKey,
+ PixmapKey
+ };
+
+ struct Flags {
+ uint type : 8;
+ uint key : 24;
+ };
+
+ union {
+ Flags flags;
+ uint bits;
+ };
+};
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
+Q_DECLARE_METATYPE(QPaintBufferCacheEntryV2)
QT_BEGIN_NAMESPACE
QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
@@ -1811,10 +1871,22 @@ QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
return stream >> entry.type >> entry.cacheKey;
}
+QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntryV2 &entry)
+{
+ return stream << entry.bits;
+}
+
+QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntryV2 &entry)
+{
+ return stream >> entry.bits;
+}
+
static int qRegisterPaintBufferMetaTypes()
{
qRegisterMetaType<QPaintBufferCacheEntry>();
qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
+ qRegisterMetaType<QPaintBufferCacheEntryV2>();
+ qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntryV2>("QPaintBufferCacheEntryV2");
return 0; // something
}
@@ -1823,6 +1895,9 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
{
+ QHash<qint64, uint> pixmapKeys;
+ QHash<qint64, uint> imageKeys;
+
QHash<qint64, QPixmap> pixmaps;
QHash<qint64, QImage> images;
@@ -1831,19 +1906,33 @@ QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
const QVariant &v = variants.at(i);
if (v.type() == QVariant::Image) {
const QImage image(v.value<QImage>());
- images[image.cacheKey()] = image;
- QPaintBufferCacheEntry entry;
- entry.type = QVariant::Image;
- entry.cacheKey = image.cacheKey();
+ QPaintBufferCacheEntryV2 entry;
+ entry.flags.type = QPaintBufferCacheEntryV2::ImageKey;
+
+ QHash<qint64, uint>::iterator it = imageKeys.find(image.cacheKey());
+ if (it != imageKeys.end()) {
+ entry.flags.key = *it;
+ } else {
+ imageKeys[image.cacheKey()] = entry.flags.key = images.size();
+ images[images.size()] = image;
+ }
+
variants[i] = QVariant::fromValue(entry);
} else if (v.type() == QVariant::Pixmap) {
const QPixmap pixmap(v.value<QPixmap>());
- pixmaps[pixmap.cacheKey()] = pixmap;
- QPaintBufferCacheEntry entry;
- entry.type = QVariant::Pixmap;
- entry.cacheKey = pixmap.cacheKey();
+ QPaintBufferCacheEntryV2 entry;
+ entry.flags.type = QPaintBufferCacheEntryV2::PixmapKey;
+
+ QHash<qint64, uint>::iterator it = pixmapKeys.find(pixmap.cacheKey());
+ if (it != pixmapKeys.end()) {
+ entry.flags.key = *it;
+ } else {
+ pixmapKeys[pixmap.cacheKey()] = entry.flags.key = pixmaps.size();
+ pixmaps[pixmaps.size()] = pixmap;
+ }
+
variants[i] = QVariant::fromValue(entry);
}
}
@@ -1885,6 +1974,15 @@ QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
variants[i] = QVariant(images.value(entry.cacheKey));
else
variants[i] = QVariant(pixmaps.value(entry.cacheKey));
+ } else if (v.canConvert<QPaintBufferCacheEntryV2>()) {
+ QPaintBufferCacheEntryV2 entry = v.value<QPaintBufferCacheEntryV2>();
+
+ if (entry.flags.type == QPaintBufferCacheEntryV2::ImageKey)
+ variants[i] = QVariant(images.value(entry.flags.key));
+ else if (entry.flags.type == QPaintBufferCacheEntryV2::PixmapKey)
+ variants[i] = QVariant(pixmaps.value(entry.flags.key));
+ else
+ qWarning() << "operator<<(QDataStream &stream, QPaintBuffer &buffer): unrecognized cache entry type:" << entry.flags.type;
}
}
diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h
index 41a26c5..8c2bb6b 100644
--- a/src/gui/painting/qpaintbuffer_p.h
+++ b/src/gui/painting/qpaintbuffer_p.h
@@ -184,6 +184,7 @@ public:
Cmd_DrawTiledPixmap,
Cmd_SystemStateChanged,
+ Cmd_Translate,
Cmd_LastCommand
};
diff --git a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
index 13044f4..6bf9d6b 100644
--- a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
+++ b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
@@ -82,8 +82,13 @@ QTraceWindowSurface::~QTraceWindowSurface()
QFile outputFile(QString(QLatin1String("qtgraphics-%0.trace")).arg(winId));
if (outputFile.open(QIODevice::WriteOnly)) {
QDataStream out(&outputFile);
- out.writeBytes("qttrace", 7);
- out << *buffer << updates;
+ out.setFloatingPointPrecision(QDataStream::SinglePrecision);
+
+ out.writeBytes("qttraceV2", 9);
+
+ uint version = 1;
+
+ out << version << *buffer << updates;
}
delete buffer;
}
diff --git a/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp b/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp
index c3afffa..86daca0 100644
--- a/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp
+++ b/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp
@@ -185,7 +185,13 @@ ReplayWidget::ReplayWidget(const QString &filename_)
char *data;
uint size;
in.readBytes(data, size);
- bool isTraceFile = size == 7 && qstrncmp(data, "qttrace", 7) == 0;
+ bool isTraceFile = size >= 7 && qstrncmp(data, "qttrace", 7) == 0;
+ uint version = 0;
+ if (size == 9 && qstrncmp(data, "qttraceV2", 9) == 0) {
+ in.setFloatingPointPrecision(QDataStream::SinglePrecision);
+ in >> version;
+ }
+
delete [] data;
if (!isTraceFile) {
printf("File '%s' is not a trace file\n", qPrintable(filename_));
@@ -193,7 +199,7 @@ ReplayWidget::ReplayWidget(const QString &filename_)
}
in >> buffer >> updates;
- printf("Read paint buffer with %d frames\n", buffer.numFrames());
+ printf("Read paint buffer version %d with %d frames\n", version, buffer.numFrames());
resize(buffer.boundingRect().size().toSize());
diff --git a/tools/qttracereplay/main.cpp b/tools/qttracereplay/main.cpp
index 82373f7..be7906b 100644
--- a/tools/qttracereplay/main.cpp
+++ b/tools/qttracereplay/main.cpp
@@ -183,15 +183,21 @@ ReplayWidget::ReplayWidget(const QString &filename_, int from_, int to_, bool si
char *data;
uint size;
in.readBytes(data, size);
- bool isTraceFile = size == 7 && qstrncmp(data, "qttrace", 7) == 0;
- delete [] data;
+ bool isTraceFile = size >= 7 && qstrncmp(data, "qttrace", 7) == 0;
+
+ uint version = 0;
+ if (size == 9 && qstrncmp(data, "qttraceV2", 9) == 0) {
+ in.setFloatingPointPrecision(QDataStream::SinglePrecision);
+ in >> version;
+ }
+
if (!isTraceFile) {
printf("File '%s' is not a trace file\n", qPrintable(filename_));
return;
}
in >> buffer >> updates;
- printf("Read paint buffer with %d frames\n", buffer.numFrames());
+ printf("Read paint buffer version %d with %d frames\n", version, buffer.numFrames());
resize(buffer.boundingRect().size().toSize());