summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2011-03-11 10:21:11 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2011-03-11 10:21:11 (GMT)
commit649e65519bef38948a818f282e3022d034dc80a5 (patch)
tree9f4b1de9322e304efd003a1f8c03047327732557 /src/openvg
parentbb7b62f3cb7aca178a9e5e65263d0a4a8d40829c (diff)
parentfcdf5a5471b7cf1d2bc72855ed1f627c8d6f4fc4 (diff)
downloadQt-649e65519bef38948a818f282e3022d034dc80a5.zip
Qt-649e65519bef38948a818f282e3022d034dc80a5.tar.gz
Qt-649e65519bef38948a818f282e3022d034dc80a5.tar.bz2
Merge remote-tracking branch 'origin/4.7' into qt-master-from-4.7
Conflicts: mkspecs/common/symbian/symbian.conf src/s60installs/bwins/QtGuiu.def src/s60installs/eabi/QtGuiu.def
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/qpaintengine_vg.cpp6
-rw-r--r--src/openvg/qpaintengine_vg_p.h2
-rw-r--r--src/openvg/qpixmapdata_vg.cpp79
-rw-r--r--src/openvg/qpixmapdata_vg_p.h20
-rw-r--r--src/openvg/qvg_symbian.cpp69
-rw-r--r--src/openvg/qwindowsurface_vgegl.cpp5
6 files changed, 161 insertions, 20 deletions
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index f0f198f..3d50558 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -2333,6 +2333,7 @@ bool QVGPaintEngine::isDefaultClipRect(const QRect& rect)
void QVGPaintEngine::clipEnabledChanged()
{
#if defined(QVG_SCISSOR_CLIP)
+ vgSeti(VG_MASKING, VG_FALSE); // disable mask fallback
updateScissor();
#else
Q_D(QVGPaintEngine);
@@ -4018,6 +4019,8 @@ VGImageFormat qt_vg_image_to_vg_format(QImage::Format format)
switch (format) {
case QImage::Format_MonoLSB:
return VG_BW_1;
+ case QImage::Format_Indexed8:
+ return VG_sL_8;
case QImage::Format_ARGB32_Premultiplied:
return VG_sARGB_8888_PRE;
case QImage::Format_RGB32:
@@ -4028,7 +4031,8 @@ VGImageFormat qt_vg_image_to_vg_format(QImage::Format format)
return VG_sRGB_565;
case QImage::Format_ARGB4444_Premultiplied:
return VG_sARGB_4444;
- default: break;
+ default:
+ break;
}
return VG_sARGB_8888; // XXX
}
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
index 85583cc..1e9103b 100644
--- a/src/openvg/qpaintengine_vg_p.h
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class QFixedPoint;
+struct QFixedPoint;
class QVGPaintEnginePrivate;
class QPixmapData;
class QVGEGLWindowSurfacePrivate;
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index c5da115..3f67c79 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -50,6 +50,7 @@
#include <QBuffer>
#include <QImageReader>
#include <QtGui/private/qimage_p.h>
+#include <QtGui/private/qnativeimagehandleprovider_p.h>
QT_BEGIN_NAMESPACE
@@ -66,6 +67,10 @@ QVGPixmapData::QVGPixmapData(PixelType type)
inImagePool = false;
inLRU = false;
failedToAlloc = false;
+#if defined(Q_OS_SYMBIAN)
+ nativeImageHandleProvider = 0;
+ nativeImageHandle = 0;
+#endif
#if !defined(QT_NO_EGL)
context = 0;
qt_vg_register_pixmap(this);
@@ -98,6 +103,10 @@ void QVGPixmapData::destroyImages()
vgImage = VG_INVALID_HANDLE;
vgImageOpacity = VG_INVALID_HANDLE;
inImagePool = false;
+
+#if defined(Q_OS_SYMBIAN)
+ releaseNativeImageHandle();
+#endif
}
void QVGPixmapData::destroyImageAndContext()
@@ -105,6 +114,8 @@ void QVGPixmapData::destroyImageAndContext()
if (vgImage != VG_INVALID_HANDLE) {
// We need to have a context current to destroy the image.
#if !defined(QT_NO_EGL)
+ if (!context)
+ context = qt_vg_create_context(0, QInternal::Pixmap);
if (context->isCurrent()) {
destroyImages();
} else {
@@ -118,6 +129,10 @@ void QVGPixmapData::destroyImageAndContext()
#else
destroyImages();
#endif
+ } else {
+#if defined(Q_OS_SYMBIAN)
+ releaseNativeImageHandle();
+#endif
}
#if !defined(QT_NO_EGL)
if (context) {
@@ -243,10 +258,7 @@ void QVGPixmapData::fill(const QColor &color)
{
if (!isValid())
return;
-
- if (source.isNull())
- source = QVolatileImage(w, h, sourceFormat());
-
+ forceToImage();
if (source.depth() == 1) {
// Pick the best approximate color in the image's colortable.
int gray = qGray(color.rgba());
@@ -258,13 +270,11 @@ void QVGPixmapData::fill(const QColor &color)
} else {
source.fill(PREMUL(color.rgba()));
}
-
- // Re-upload the image to VG the next time toVGImage() is called.
- recreate = true;
}
bool QVGPixmapData::hasAlphaChannel() const
{
+ ensureReadback(true);
if (!source.isNull())
return source.hasAlphaChannel();
else
@@ -273,6 +283,8 @@ bool QVGPixmapData::hasAlphaChannel() const
void QVGPixmapData::setAlphaChannel(const QPixmap &alphaChannel)
{
+ if (!isValid())
+ return;
forceToImage();
source.setAlphaChannel(alphaChannel);
}
@@ -281,12 +293,11 @@ QImage QVGPixmapData::toImage() const
{
if (!isValid())
return QImage();
-
+ ensureReadback(true);
if (source.isNull()) {
source = QVolatileImage(w, h, sourceFormat());
recreate = true;
}
-
return source.toImage();
}
@@ -345,6 +356,12 @@ VGImage QVGPixmapData::toVGImage()
else if (recreate)
cachedOpacity = -1.0f; // Force opacity image to be refreshed later.
+#if defined(Q_OS_SYMBIAN)
+ if (recreate && nativeImageHandleProvider && !nativeImageHandle) {
+ createFromNativeImageHandleProvider();
+ }
+#endif
+
if (vgImage == VG_INVALID_HANDLE) {
vgImage = QVGImagePool::instance()->createImageForPixmap
(qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this);
@@ -429,9 +446,16 @@ void QVGPixmapData::detachImageFromPool()
void QVGPixmapData::hibernate()
{
- // If the image was imported (e.g, from an SgImage under Symbian),
- // then we cannot copy it back to main memory for storage.
- if (vgImage != VG_INVALID_HANDLE && source.isNull())
+ // If the image was imported (e.g, from an SgImage under Symbian), then
+ // skip the hibernation, there is no sense in copying it back to main
+ // memory because the data is most likely shared between several processes.
+ bool skipHibernate = (vgImage != VG_INVALID_HANDLE && source.isNull());
+#if defined(Q_OS_SYMBIAN)
+ // However we have to proceed normally if the image was retrieved via
+ // a handle provider.
+ skipHibernate &= !nativeImageHandleProvider;
+#endif
+ if (skipHibernate)
return;
forceToImage();
@@ -476,18 +500,47 @@ int QVGPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
}
}
-// Force the pixmap data to be backed by some valid data.
+// Ensures that the pixmap is backed by some valid data and forces the data to
+// be re-uploaded to the VGImage when toVGImage() is called next time.
void QVGPixmapData::forceToImage()
{
if (!isValid())
return;
+ ensureReadback(false);
+
if (source.isNull())
source = QVolatileImage(w, h, sourceFormat());
recreate = true;
}
+void QVGPixmapData::ensureReadback(bool readOnly) const
+{
+ if (vgImage != VG_INVALID_HANDLE && source.isNull()) {
+ source = QVolatileImage(w, h, sourceFormat());
+ source.beginDataAccess();
+ vgGetImageSubData(vgImage, source.bits(), source.bytesPerLine(),
+ qt_vg_image_to_vg_format(source.format()),
+ 0, 0, w, h);
+ source.endDataAccess();
+ if (readOnly) {
+ recreate = false;
+ } else {
+ // Once we did a readback, the original VGImage must be destroyed
+ // because it may be shared (e.g. created via SgImage) and a subsequent
+ // upload of the image data may produce unexpected results.
+ const_cast<QVGPixmapData *>(this)->destroyImages();
+#if defined(Q_OS_SYMBIAN)
+ // There is now an own copy of the data so drop the handle provider,
+ // otherwise toVGImage() would request the handle again, which is wrong.
+ nativeImageHandleProvider = 0;
+#endif
+ recreate = true;
+ }
+ }
+}
+
QImage::Format QVGPixmapData::sourceFormat() const
{
return QImage::Format_ARGB32_Premultiplied;
diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h
index c4fd47f..15ff889 100644
--- a/src/openvg/qpixmapdata_vg_p.h
+++ b/src/openvg/qpixmapdata_vg_p.h
@@ -55,7 +55,7 @@
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qvolatileimage_p.h>
-#include <private/qvg_p.h>
+#include "qvg_p.h"
#if defined(Q_OS_SYMBIAN)
class RSGImage;
@@ -76,6 +76,8 @@ void qt_vg_unregister_pixmap(QVGPixmapData *pd);
void qt_vg_hibernate_pixmaps(QVGSharedContext *context);
#endif
+class QNativeImageHandleProvider;
+
class Q_OPENVG_EXPORT QVGPixmapData : public QPixmapData
{
public:
@@ -126,11 +128,21 @@ public:
// VGImage objects to reuse storage.
virtual void reclaimImages();
+ // If vgImage is valid but source is null, copies pixel data from GPU back
+ // into main memory and destroys vgImage. For a normal pixmap this function
+ // does nothing, however if the pixmap was created directly from a VGImage
+ // (e.g. via SgImage on Symbian) then by doing the readback this ensures
+ // that QImage-based functions can operate too.
+ virtual void ensureReadback(bool readOnly) const;
+
QSize size() const { return QSize(w, h); }
#if defined(Q_OS_SYMBIAN)
void* toNativeType(NativeType type);
void fromNativeType(void* pixmap, NativeType type);
+ bool initFromNativeImageHandle(void *handle, const QString &type);
+ void createFromNativeImageHandleProvider();
+ void releaseNativeImageHandle();
#endif
protected:
@@ -170,6 +182,12 @@ protected:
mutable QEglContext *context;
#endif
+#if defined(Q_OS_SYMBIAN)
+ mutable QNativeImageHandleProvider *nativeImageHandleProvider;
+ void *nativeImageHandle;
+ QString nativeImageType;
+#endif
+
void forceToImage();
QImage::Format sourceFormat() const;
QImage::Format idealFormat(QImage *image, Qt::ImageConversionFlags flags) const;
diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp
index 22cbb3c..2924d41 100644
--- a/src/openvg/qvg_symbian.cpp
+++ b/src/openvg/qvg_symbian.cpp
@@ -41,6 +41,7 @@
#include "qpixmapdata_vg_p.h"
#include "qvgfontglyphcache_p.h"
+#include <QtGui/private/qnativeimagehandleprovider_p.h>
#include <private/qt_s60_p.h>
#include <fbs.h>
@@ -111,6 +112,58 @@ void QVGPixmapData::cleanup()
source = QVolatileImage();
}
+bool QVGPixmapData::initFromNativeImageHandle(void *handle, const QString &type)
+{
+ if (type == QLatin1String("RSgImage")) {
+ fromNativeType(handle, QPixmapData::SgImage);
+ return true;
+ } else if (type == QLatin1String("CFbsBitmap")) {
+ fromNativeType(handle, QPixmapData::FbsBitmap);
+ return true;
+ }
+ return false;
+}
+
+void QVGPixmapData::createFromNativeImageHandleProvider()
+{
+ void *handle = 0;
+ QString type;
+ nativeImageHandleProvider->get(&handle, &type);
+ if (handle) {
+ if (initFromNativeImageHandle(handle, type)) {
+ nativeImageHandle = handle;
+ nativeImageType = type;
+ } else {
+ qWarning("QVGPixmapData: Unknown native image type '%s'", qPrintable(type));
+ }
+ } else {
+ qWarning("QVGPixmapData: Native handle is null");
+ }
+}
+
+void QVGPixmapData::releaseNativeImageHandle()
+{
+ if (nativeImageHandleProvider && nativeImageHandle) {
+ nativeImageHandleProvider->release(nativeImageHandle, nativeImageType);
+ nativeImageHandle = 0;
+ nativeImageType = QString();
+ }
+}
+
+static inline bool conversionLessFormat(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_RGB16: // EColor64K
+ case QImage::Format_RGB32: // EColor16MU
+ case QImage::Format_ARGB32: // EColor16MA
+ case QImage::Format_ARGB32_Premultiplied: // EColor16MAP
+ case QImage::Format_Indexed8: // EGray256, EColor256
+ return true;
+ default:
+ return false;
+ }
+}
+
void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
{
if (type == QPixmapData::SgImage && pixmap) {
@@ -127,7 +180,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
}
is_null = (w <= 0 || h <= 0);
- source = QVolatileImage(); // vgGetImageSubData() some day?
+ source = QVolatileImage(); // readback will be done later, only when needed
recreate = false;
prevSize = QSize(w, h);
updateSerial();
@@ -139,9 +192,11 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
source = QVolatileImage(bitmap); // duplicates only, if possible
if (source.isNull())
return;
- // Here we may need to copy if the formats do not match.
- // (e.g. for display modes other than EColor16MAP and EColor16MU)
- source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor));
+ if (!conversionLessFormat(source.format())) {
+ // Here we may need to copy if the formats do not match.
+ // (e.g. for display modes other than EColor16MAP and EColor16MU)
+ source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor));
+ }
recreate = true;
} else if (type == QPixmapData::VolatileImage && pixmap) {
QVolatileImage *img = static_cast<QVolatileImage *>(pixmap);
@@ -149,6 +204,11 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
source = *img;
source.ensureFormat(idealFormat(&source.imageRef(), Qt::AutoColor));
recreate = true;
+ } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) {
+ destroyImages();
+ nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap);
+ // Cannot defer the retrieval, we need at least the size right away.
+ createFromNativeImageHandleProvider();
}
}
@@ -216,6 +276,7 @@ void* QVGPixmapData::toNativeType(NativeType type)
return reinterpret_cast<void*>(sgImage.take());
#endif
} else if (type == QPixmapData::FbsBitmap && isValid()) {
+ ensureReadback(true);
if (source.isNull()) {
source = QVolatileImage(w, h, sourceFormat());
}
diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp
index ca80886..866453f 100644
--- a/src/openvg/qwindowsurface_vgegl.cpp
+++ b/src/openvg/qwindowsurface_vgegl.cpp
@@ -768,6 +768,11 @@ bool QVGEGLWindowSurfaceDirect::scroll(QWidget *widget, const QRegion& area, int
context->lazyDoneCurrent();
return true;
}
+#else
+ Q_UNUSED(widget);
+ Q_UNUSED(area);
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
#endif
return false;
}