diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-06-15 15:27:55 (GMT) |
---|---|---|
committer | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-06-16 08:15:03 (GMT) |
commit | 6afe7a233e66f0cae803590d536b4d379b7c1625 (patch) | |
tree | 9885124e37367b7fb2ec967db3c4c4fbdfdcab07 /src | |
parent | 5e35452ad8420886f54df89d19205acb88ebb363 (diff) | |
download | Qt-6afe7a233e66f0cae803590d536b4d379b7c1625.zip Qt-6afe7a233e66f0cae803590d536b4d379b7c1625.tar.gz Qt-6afe7a233e66f0cae803590d536b4d379b7c1625.tar.bz2 |
Handle QVolatileImage-backed pixmaps optimally in drawPixmap().
When drawing such pixmaps (used by both the openvg and opengl graphics
systems) onto another pixmap or to a QImage, the performance was
sub-optimal due to missing and accidentally disabled support
specific to QVolatileImage. This is now fixed and drawing pixmaps into
a QImage is also made optimal by using the QS60PaintEngine for
QImage too. This will cause a 5-7x (or even up to 12x on certain
hardware and platform) increase in offscreen pixmap drawing
performance.
Task-number: QTBUG-19880
Reviewed-by: Jani Hautakangas
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/image/qimage.cpp | 8 | ||||
-rw-r--r-- | src/gui/image/qpixmapdata.cpp | 5 | ||||
-rw-r--r-- | src/gui/image/qpixmapdata_p.h | 2 | ||||
-rw-r--r-- | src/gui/image/qvolatileimage.cpp | 35 | ||||
-rw-r--r-- | src/gui/image/qvolatileimage_p.h | 1 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_s60.cpp | 30 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_s60_p.h | 2 | ||||
-rw-r--r-- | src/opengl/qgl_symbian.cpp | 1 | ||||
-rw-r--r-- | src/openvg/qpixmapdata_vg.cpp | 3 | ||||
-rw-r--r-- | src/openvg/qpixmapdata_vg_p.h | 2 | ||||
-rw-r--r-- | src/openvg/qvg_symbian.cpp | 5 |
11 files changed, 62 insertions, 32 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 65793af..d7156a7 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -62,7 +62,11 @@ #include <qhash.h> +#if defined(Q_OS_SYMBIAN) +#include <private/qpaintengine_s60_p.h> +#else #include <private/qpaintengine_raster_p.h> +#endif #include <private/qimage_p.h> @@ -5706,7 +5710,11 @@ QPaintEngine *QImage::paintEngine() const return 0; if (!d->paintEngine) { +#ifdef Q_OS_SYMBIAN + d->paintEngine = new QS60PaintEngine(const_cast<QImage *>(this)); +#else d->paintEngine = new QRasterPaintEngine(const_cast<QImage *>(this)); +#endif } return d->paintEngine; diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index c46429c..934dbb8 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -276,6 +276,11 @@ QImage* QPixmapData::buffer() } #if defined(Q_OS_SYMBIAN) +QVolatileImage QPixmapData::toVolatileImage() const +{ + return QVolatileImage(); +} + void* QPixmapData::toNativeType(NativeType /* type */) { return 0; diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 099c61c..cf089fb 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -138,7 +138,7 @@ public: } #if defined(Q_OS_SYMBIAN) - virtual QVolatileImage toVolatileImage() const { return QVolatileImage(); } + virtual QVolatileImage toVolatileImage() const; virtual void* toNativeType(NativeType type); virtual void fromNativeType(void* pixmap, NativeType type); #endif diff --git a/src/gui/image/qvolatileimage.cpp b/src/gui/image/qvolatileimage.cpp index b8612b1..9734c82 100644 --- a/src/gui/image/qvolatileimage.cpp +++ b/src/gui/image/qvolatileimage.cpp @@ -200,6 +200,16 @@ QImage &QVolatileImage::imageRef() // non-const, in order to cause a detach return d->image; } +/*! + Non-detaching version, for read-only access only. + Must be guarded by begin/endDataAccess(). + */ +const QImage &QVolatileImage::constImageRef() const +{ + const_cast<QVolatileImageData *>(d.data())->ensureImage(); + return d->image; +} + void *QVolatileImage::duplicateNativeImage() const { return d->duplicateNativeImage(); @@ -289,12 +299,14 @@ bool QVolatileImagePaintEngine::end() void QVolatileImagePaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) { #ifdef Q_OS_SYMBIAN - void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); - if (nativeData) { - QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); - img->beginDataAccess(); - QRasterPaintEngine::drawImage(p, img->imageRef()); - img->endDataAccess(true); + QVolatileImage img = pm.pixmapData()->toVolatileImage(); + if (!img.isNull()) { + img.beginDataAccess(); + // imageRef() would detach and since we received the QVolatileImage from + // toVolatileImage() by value, it would cause a copy which would ruin + // our goal. So use constImageRef() instead. + QRasterPaintEngine::drawImage(p, img.constImageRef()); + img.endDataAccess(true); } else { QRasterPaintEngine::drawPixmap(p, pm); } @@ -306,12 +318,11 @@ void QVolatileImagePaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) void QVolatileImagePaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) { #ifdef Q_OS_SYMBIAN - void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); - if (nativeData) { - QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); - img->beginDataAccess(); - QRasterPaintEngine::drawImage(r, img->imageRef(), sr); - img->endDataAccess(true); + QVolatileImage img = pm.pixmapData()->toVolatileImage(); + if (!img.isNull()) { + img.beginDataAccess(); + QRasterPaintEngine::drawImage(r, img.constImageRef(), sr); + img.endDataAccess(true); } else { QRasterPaintEngine::drawPixmap(r, pm, sr); } diff --git a/src/gui/image/qvolatileimage_p.h b/src/gui/image/qvolatileimage_p.h index 97d6ea6..bed2e91 100644 --- a/src/gui/image/qvolatileimage_p.h +++ b/src/gui/image/qvolatileimage_p.h @@ -87,6 +87,7 @@ public: bool ensureFormat(QImage::Format format); QImage toImage() const; QImage &imageRef(); + const QImage &constImageRef() const; QPaintEngine *paintEngine(); void setAlphaChannel(const QPixmap &alphaChannel); void fill(uint pixelValue); diff --git a/src/gui/painting/qpaintengine_s60.cpp b/src/gui/painting/qpaintengine_s60.cpp index 091e2e6..fd7bea2 100644 --- a/src/gui/painting/qpaintengine_s60.cpp +++ b/src/gui/painting/qpaintengine_s60.cpp @@ -60,7 +60,7 @@ bool QS60PaintEngine::begin(QPaintDevice *device) { Q_D(QS60PaintEngine); - if (pixmapData->classId() == QPixmapData::RasterClass) { + if (pixmapData && pixmapData->classId() == QPixmapData::RasterClass) { pixmapData->beginDataAccess(); bool ret = QRasterPaintEngine::begin(device); // Make sure QPaintEngine::paintDevice() returns the proper device. @@ -69,13 +69,12 @@ bool QS60PaintEngine::begin(QPaintDevice *device) d->pdev = device; return ret; } - return QRasterPaintEngine::begin(device); } bool QS60PaintEngine::end() { - if (pixmapData->classId() == QPixmapData::RasterClass) { + if (pixmapData && pixmapData->classId() == QPixmapData::RasterClass) { bool ret = QRasterPaintEngine::end(); pixmapData->endDataAccess(); return ret; @@ -91,12 +90,14 @@ void QS60PaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) QRasterPaintEngine::drawPixmap(p, pm); srcData->endDataAccess(); } else { - void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); - if (nativeData) { - QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); - img->beginDataAccess(); - QRasterPaintEngine::drawImage(p, img->imageRef()); - img->endDataAccess(true); + QVolatileImage img = pm.pixmapData()->toVolatileImage(); + if (!img.isNull()) { + img.beginDataAccess(); + // imageRef() would detach and since we received the QVolatileImage + // from toVolatileImage() by value, it would cause a copy which + // would ruin our goal. So use constImageRef() instead. + QRasterPaintEngine::drawImage(p, img.constImageRef()); + img.endDataAccess(true); } else { QRasterPaintEngine::drawPixmap(p, pm); } @@ -111,12 +112,11 @@ void QS60PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRect QRasterPaintEngine::drawPixmap(r, pm, sr); srcData->endDataAccess(); } else { - void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); - if (nativeData) { - QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); - img->beginDataAccess(); - QRasterPaintEngine::drawImage(r, img->imageRef(), sr); - img->endDataAccess(true); + QVolatileImage img = pm.pixmapData()->toVolatileImage(); + if (!img.isNull()) { + img.beginDataAccess(); + QRasterPaintEngine::drawImage(r, img.constImageRef(), sr); + img.endDataAccess(true); } else { QRasterPaintEngine::drawPixmap(r, pm, sr); } diff --git a/src/gui/painting/qpaintengine_s60_p.h b/src/gui/painting/qpaintengine_s60_p.h index 2a3b443..5535c24 100644 --- a/src/gui/painting/qpaintengine_s60_p.h +++ b/src/gui/painting/qpaintengine_s60_p.h @@ -65,7 +65,7 @@ class QS60PaintEngine : public QRasterPaintEngine Q_DECLARE_PRIVATE(QS60PaintEngine) public: - QS60PaintEngine(QPaintDevice *device, QS60PixmapData* data); + QS60PaintEngine(QPaintDevice *device, QS60PixmapData *data = 0); bool begin(QPaintDevice *device); bool end(); diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp index 86176c9..20c2170 100644 --- a/src/opengl/qgl_symbian.cpp +++ b/src/opengl/qgl_symbian.cpp @@ -437,7 +437,6 @@ void* QGLPixmapData::toNativeType(NativeType type) m_source = QVolatileImage(w, h, QImage::Format_ARGB32_Premultiplied); return m_source.duplicateNativeImage(); } - return 0; } diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index a5d156d..1231abf 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -248,9 +248,10 @@ void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags // same. Detaching is needed to prevent issues with painting // onto this QPixmap later on. convertedImage.detach(); + if (convertedImage.isNull()) + qWarning("QVGPixmapData: Failed to convert image data (out of memory? try increasing heap size)"); source = QVolatileImage(convertedImage); } - recreate = true; } diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h index 18846f3..4a969c0 100644 --- a/src/openvg/qpixmapdata_vg_p.h +++ b/src/openvg/qpixmapdata_vg_p.h @@ -138,7 +138,7 @@ public: QSize size() const { return QSize(w, h); } #if defined(Q_OS_SYMBIAN) - QVolatileImage toVolatileImage() const { return source; } + QVolatileImage toVolatileImage() const; void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); bool initFromNativeImageHandle(void *handle, const QString &type); diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 249b053..98a5869 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -288,6 +288,11 @@ void* QVGPixmapData::toNativeType(NativeType type) return 0; } +QVolatileImage QVGPixmapData::toVolatileImage() const +{ + return source; +} + QSymbianVGFontGlyphCache::QSymbianVGFontGlyphCache() : QVGFontGlyphCache() { #ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE |