summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-06-15 15:27:55 (GMT)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>2011-06-16 08:15:03 (GMT)
commit6afe7a233e66f0cae803590d536b4d379b7c1625 (patch)
tree9885124e37367b7fb2ec967db3c4c4fbdfdcab07
parent5e35452ad8420886f54df89d19205acb88ebb363 (diff)
downloadQt-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
-rw-r--r--src/gui/image/qimage.cpp8
-rw-r--r--src/gui/image/qpixmapdata.cpp5
-rw-r--r--src/gui/image/qpixmapdata_p.h2
-rw-r--r--src/gui/image/qvolatileimage.cpp35
-rw-r--r--src/gui/image/qvolatileimage_p.h1
-rw-r--r--src/gui/painting/qpaintengine_s60.cpp30
-rw-r--r--src/gui/painting/qpaintengine_s60_p.h2
-rw-r--r--src/opengl/qgl_symbian.cpp1
-rw-r--r--src/openvg/qpixmapdata_vg.cpp3
-rw-r--r--src/openvg/qpixmapdata_vg_p.h2
-rw-r--r--src/openvg/qvg_symbian.cpp5
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