summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/qpaintengine_vg.cpp86
-rw-r--r--src/openvg/qpaintengine_vg_p.h1
-rw-r--r--src/openvg/qpixmapdata_vg.cpp27
-rw-r--r--src/openvg/qpixmapdata_vg_p.h2
-rw-r--r--src/openvg/qvg_symbian.cpp1
5 files changed, 101 insertions, 16 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index f8788b0..8405ead 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -55,6 +55,8 @@
#include <QtGui/private/qfontengine_p.h>
#include <QtGui/private/qpainterpath_p.h>
#include <QtGui/private/qstatictext_p.h>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
#include <QtCore/qmath.h>
#include <QDebug>
#include <QSet>
@@ -3060,6 +3062,21 @@ void qt_vg_drawVGImageStencil
vgDrawImage(vgImg);
}
+bool QVGPaintEngine::canVgWritePixels(const QImage &image) const
+{
+ Q_D(const QVGPaintEngine);
+ // vgWritePixels ignores masking, blending and xforms so we can only use it if
+ // ALL of the following conditions are true:
+ // - It is a simple translate, or a scale of -1 on the y-axis (inverted)
+ // - The opacity is totally opaque
+ // - The composition mode is "source" OR "source over" provided the image is opaque
+ return ( d->imageTransform.type() <= QTransform::TxScale
+ && d->imageTransform.m11() == 1.0 && qAbs(d->imageTransform.m22()) == 1.0)
+ && d->opacity == 1.0f
+ && (d->blendMode == VG_BLEND_SRC || (d->blendMode == VG_BLEND_SRC_OVER &&
+ !image.hasAlphaChannel()));
+}
+
void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
{
QPixmapData *pd = pm.pixmapData();
@@ -3074,9 +3091,18 @@ void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF
drawVGImage(d, r, vgpd->toVGImage(), vgpd->size(), sr);
else
drawVGImage(d, r, vgpd->toVGImage(d->opacity), vgpd->size(), sr);
- } else {
- drawImage(r, *(pd->buffer()), sr, Qt::AutoColor);
+
+ if(!vgpd->failedToAlloc)
+ return;
+
+ // try to reallocate next time if reasonable small pixmap
+ QSize screenSize = QApplication::desktop()->screenGeometry().size();
+ if (pm.size().width() <= screenSize.width()
+ && pm.size().height() <= screenSize.height())
+ vgpd->failedToAlloc = false;
}
+
+ drawImage(r, *(pd->buffer()), sr, Qt::AutoColor);
}
void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
@@ -3093,9 +3119,18 @@ void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
drawVGImage(d, pos, vgpd->toVGImage());
else
drawVGImage(d, pos, vgpd->toVGImage(d->opacity));
- } else {
- drawImage(pos, *(pd->buffer()));
+
+ if (!vgpd->failedToAlloc)
+ return;
+
+ // try to reallocate next time if reasonable small pixmap
+ QSize screenSize = QApplication::desktop()->screenGeometry().size();
+ if (pm.size().width() <= screenSize.width()
+ && pm.size().height() <= screenSize.height())
+ vgpd->failedToAlloc = false;
}
+
+ drawImage(pos, *(pd->buffer()));
}
void QVGPaintEngine::drawImage
@@ -3116,9 +3151,31 @@ void QVGPaintEngine::drawImage
QRectF(QPointF(0, 0), sr.size()));
}
} else {
- // Monochrome images need to use the vgChildImage() path.
- vgImg = toVGImage(image, flags);
- drawVGImage(d, r, vgImg, image.size(), sr);
+ if (canVgWritePixels(image) && (r.size() == sr.size()) && !flags) {
+ // Optimization for straight blits, no blending
+ int x = sr.x();
+ int y = sr.y();
+ int bpp = image.depth() >> 3; // bytes
+ int offset = 0;
+ int bpl = image.bytesPerLine();
+ if (d->imageTransform.m22() < 0) {
+ // inverted
+ offset = ((y + sr.height()) * bpl) - ((image.width() - x) * bpp);
+ bpl = -bpl;
+ } else {
+ offset = (y * bpl) + (x * bpp);
+ }
+ const uchar *bits = image.constBits() + offset;
+
+ QPointF mapped = d->imageTransform.map(r.topLeft());
+ vgWritePixels(bits, bpl, qt_vg_image_to_vg_format(image.format()),
+ mapped.x(), mapped.y() - sr.height(), r.width(), r.height());
+ return;
+ } else {
+ // Monochrome images need to use the vgChildImage() path.
+ vgImg = toVGImage(image, flags);
+ drawVGImage(d, r, vgImg, image.size(), sr);
+ }
}
vgDestroyImage(vgImg);
}
@@ -3127,10 +3184,21 @@ void QVGPaintEngine::drawImage(const QPointF &pos, const QImage &image)
{
Q_D(QVGPaintEngine);
VGImage vgImg;
- if (d->simpleTransform || d->opacity == 1.0f)
+ if (canVgWritePixels(image)) {
+ // Optimization for straight blits, no blending
+ bool inverted = (d->imageTransform.m22() < 0);
+ const uchar *bits = inverted ? image.constBits() + image.byteCount() : image.constBits();
+ int bpl = inverted ? -image.bytesPerLine() : image.bytesPerLine();
+
+ QPointF mapped = d->imageTransform.map(pos);
+ vgWritePixels(bits, bpl, qt_vg_image_to_vg_format(image.format()),
+ mapped.x(), mapped.y() - image.height(), image.width(), image.height());
+ return;
+ } else if (d->simpleTransform || d->opacity == 1.0f) {
vgImg = toVGImage(image);
- else
+ } else {
vgImg = toVGImageWithOpacity(image, d->opacity);
+ }
drawVGImage(d, pos, vgImg);
vgDestroyImage(vgImg);
}
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
index 75cf053..dc98137 100644
--- a/src/openvg/qpaintengine_vg_p.h
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -170,6 +170,7 @@ private:
bool isDefaultClipRegion(const QRegion& region);
bool isDefaultClipRect(const QRect& rect);
bool clearRect(const QRectF &rect, const QColor &color);
+ bool canVgWritePixels(const QImage &image) const;
};
QT_END_NAMESPACE
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index e8ec333..509882b 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -65,6 +65,7 @@ QVGPixmapData::QVGPixmapData(PixelType type)
recreate = true;
inImagePool = false;
inLRU = false;
+ failedToAlloc = false;
#if !defined(QT_NO_EGL)
context = 0;
qt_vg_register_pixmap(this);
@@ -155,6 +156,9 @@ void QVGPixmapData::resize(int wid, int ht)
void QVGPixmapData::fromImage
(const QImage &image, Qt::ImageConversionFlags flags)
{
+ if(image.isNull())
+ return;
+
QImage img = image;
createPixmapForImage(img, flags, false);
}
@@ -203,10 +207,19 @@ void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags
else
resize(image.width(), image.height());
- if (inPlace && image.data_ptr()->convertInPlace(sourceFormat(), flags))
+ QImage::Format format = sourceFormat();
+ int d = image.depth();
+ if (d == 1 || d == 16 || d == 24 || (d == 32 && !image.hasAlphaChannel()))
+ format = QImage::Format_RGB32;
+ else if (!(flags & Qt::NoOpaqueDetection) && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
+ format = sourceFormat();
+ else
+ format = QImage::Format_RGB32;
+
+ if (inPlace && image.data_ptr()->convertInPlace(format, flags))
source = image;
else
- source = image.convertToFormat(sourceFormat());
+ source = image.convertToFormat(format);
recreate = true;
}
@@ -278,7 +291,7 @@ QPaintEngine* QVGPixmapData::paintEngine() const
VGImage QVGPixmapData::toVGImage()
{
- if (!isValid())
+ if (!isValid() || failedToAlloc)
return VG_INVALID_HANDLE;
#if !defined(QT_NO_EGL)
@@ -294,11 +307,13 @@ VGImage QVGPixmapData::toVGImage()
if (vgImage == VG_INVALID_HANDLE) {
vgImage = QVGImagePool::instance()->createImageForPixmap
- (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this);
+ (qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this);
// Bail out if we run out of GPU memory - try again next time.
- if (vgImage == VG_INVALID_HANDLE)
+ if (vgImage == VG_INVALID_HANDLE) {
+ failedToAlloc = true;
return VG_INVALID_HANDLE;
+ }
inImagePool = true;
} else if (inImagePool) {
@@ -309,7 +324,7 @@ VGImage QVGPixmapData::toVGImage()
vgImageSubData
(vgImage,
source.constBits(), source.bytesPerLine(),
- VG_sARGB_8888_PRE, 0, 0, w, h);
+ qt_vg_image_to_vg_format(source.format()), 0, 0, w, h);
}
recreate = false;
diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h
index 114d545..7ffdc85 100644
--- a/src/openvg/qpixmapdata_vg_p.h
+++ b/src/openvg/qpixmapdata_vg_p.h
@@ -143,7 +143,9 @@ private:
QVGPixmapData *nextLRU;
QVGPixmapData *prevLRU;
bool inLRU;
+ bool failedToAlloc;
friend class QVGImagePool;
+ friend class QVGPaintEngine;
#if !defined(QT_NO_EGL)
QVGPixmapData *next;
diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp
index 41b35fc..c608c81 100644
--- a/src/openvg/qvg_symbian.cpp
+++ b/src/openvg/qvg_symbian.cpp
@@ -164,7 +164,6 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
bool deleteSourceBitmap = false;
-
#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
// Rasterize extended bitmaps