summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/openvg.pro6
-rw-r--r--src/openvg/qpaintengine_vg.cpp16
-rw-r--r--src/openvg/qpixmapdata_vg.cpp100
-rw-r--r--src/openvg/qpixmapdata_vg_p.h17
-rw-r--r--src/openvg/qpixmapfilter_vg.cpp25
-rw-r--r--src/openvg/qvgimagepool.cpp215
-rw-r--r--src/openvg/qvgimagepool_p.h157
-rw-r--r--src/openvg/qwindowsurface_vgegl.cpp4
8 files changed, 487 insertions, 53 deletions
diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro
index 8927c4c..c8c9917 100644
--- a/src/openvg/openvg.pro
+++ b/src/openvg/openvg.pro
@@ -16,11 +16,13 @@ HEADERS += \
qpaintengine_vg_p.h \
qpixmapdata_vg_p.h \
qpixmapfilter_vg_p.h \
- qvgcompositionhelper_p.h
+ qvgcompositionhelper_p.h \
+ qvgimagepool_p.h
SOURCES += \
qpaintengine_vg.cpp \
qpixmapdata_vg.cpp \
- qpixmapfilter_vg.cpp
+ qpixmapfilter_vg.cpp \
+ qvgimagepool.cpp
contains(QT_CONFIG, egl) {
HEADERS += \
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index 6b829dd..04fee08 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -43,6 +43,7 @@
#include "qpixmapdata_vg_p.h"
#include "qpixmapfilter_vg_p.h"
#include "qvgcompositionhelper_p.h"
+#include "qvgimagepool_p.h"
#if !defined(QT_NO_EGL)
#include <QtGui/private/qegl_p.h>
#include "qwindowsurface_vgegl_p.h"
@@ -1018,7 +1019,7 @@ static VGImage toVGImage
const uchar *pixels = img.bits();
- VGImage vgImg = vgCreateImage
+ VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
vgImageSubData
(vgImg, pixels, img.bytesPerLine(), format, 0, 0,
@@ -1063,7 +1064,7 @@ static VGImage toVGImageSubRect
const uchar *pixels = img.bits() + bpp * sr.x() +
img.bytesPerLine() * sr.y();
- VGImage vgImg = vgCreateImage
+ VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER);
vgImageSubData
(vgImg, pixels, img.bytesPerLine(), format, 0, 0,
@@ -1084,7 +1085,7 @@ static VGImage toVGImageWithOpacity(const QImage & image, qreal opacity)
const uchar *pixels = img.bits();
- VGImage vgImg = vgCreateImage
+ VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
vgImageSubData
(vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
@@ -1106,7 +1107,7 @@ static VGImage toVGImageWithOpacitySubRect
const uchar *pixels = img.bits();
- VGImage vgImg = vgCreateImage
+ VGImage vgImg = QVGImagePool::instance()->createPermanentImage
(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
vgImageSubData
(vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
@@ -1194,6 +1195,12 @@ VGPaintType QVGPaintEnginePrivate::setBrush
if (pd->classId() == QPixmapData::OpenVGClass) {
QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
vgImg = vgpd->toVGImage();
+
+ // We don't want the pool to reclaim this image
+ // because we cannot predict when the paint object
+ // will stop using it. Replacing the image with
+ // new data will make the paint object invalid.
+ vgpd->detachImageFromPool();
} else {
vgImg = toVGImage(*(pd->buffer()));
deref = true;
@@ -1201,6 +1208,7 @@ VGPaintType QVGPaintEnginePrivate::setBrush
} else if (pd->classId() == QPixmapData::OpenVGClass) {
QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
vgImg = vgpd->toVGImage(opacity);
+ vgpd->detachImageFromPool();
} else {
vgImg = toVGImageWithOpacity(*(pd->buffer()), opacity);
deref = true;
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index 5d5fcbf..358ec4d 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -43,6 +43,7 @@
#include "qpaintengine_vg_p.h"
#include <QtGui/private/qdrawhelper_p.h>
#include "qvg_p.h"
+#include "qvgimagepool_p.h"
#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
#include <graphics/sgimage.h>
@@ -63,6 +64,8 @@ QVGPixmapData::QVGPixmapData(PixelType type)
vgImageOpacity = VG_INVALID_HANDLE;
cachedOpacity = 1.0f;
recreate = true;
+ inImagePool = false;
+ inLRU = false;
#if !defined(QT_NO_EGL)
context = 0;
qt_vg_register_pixmap(this);
@@ -78,32 +81,43 @@ QVGPixmapData::~QVGPixmapData()
#endif
}
+void QVGPixmapData::destroyImages()
+{
+ if (inImagePool) {
+ QVGImagePool *pool = QVGImagePool::instance();
+ if (vgImage != VG_INVALID_HANDLE)
+ pool->releaseImage(this, vgImage);
+ if (vgImageOpacity != VG_INVALID_HANDLE)
+ pool->releaseImage(this, vgImageOpacity);
+ } else {
+ if (vgImage != VG_INVALID_HANDLE)
+ vgDestroyImage(vgImage);
+ if (vgImageOpacity != VG_INVALID_HANDLE)
+ vgDestroyImage(vgImageOpacity);
+ }
+ vgImage = VG_INVALID_HANDLE;
+ vgImageOpacity = VG_INVALID_HANDLE;
+ inImagePool = false;
+}
+
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->isCurrent()) {
- vgDestroyImage(vgImage);
- if (vgImageOpacity != VG_INVALID_HANDLE)
- vgDestroyImage(vgImageOpacity);
+ destroyImages();
} else {
// We don't currently have a widget surface active, but we
// need a surface to make the context current. So use the
// shared pbuffer surface instead.
context->makeCurrent(qt_vg_shared_surface());
- vgDestroyImage(vgImage);
- if (vgImageOpacity != VG_INVALID_HANDLE)
- vgDestroyImage(vgImageOpacity);
+ destroyImages();
context->lazyDoneCurrent();
}
#else
- vgDestroyImage(vgImage);
- if (vgImageOpacity != VG_INVALID_HANDLE)
- vgDestroyImage(vgImageOpacity);
+ destroyImages();
#endif
- vgImage = VG_INVALID_HANDLE;
- vgImageOpacity = VG_INVALID_HANDLE;
}
#if !defined(QT_NO_EGL)
if (context) {
@@ -234,22 +248,22 @@ VGImage QVGPixmapData::toVGImage()
context = qt_vg_create_context(0, QInternal::Pixmap);
#endif
- if (recreate && prevSize != QSize(w, h)) {
- if (vgImage != VG_INVALID_HANDLE) {
- vgDestroyImage(vgImage);
- vgImage = VG_INVALID_HANDLE;
- }
- if (vgImageOpacity != VG_INVALID_HANDLE) {
- vgDestroyImage(vgImageOpacity);
- vgImageOpacity = VG_INVALID_HANDLE;
- }
- } else if (recreate) {
+ if (recreate && prevSize != QSize(w, h))
+ destroyImages();
+ else if (recreate)
cachedOpacity = -1.0f; // Force opacity image to be refreshed later.
- }
if (vgImage == VG_INVALID_HANDLE) {
- vgImage = vgCreateImage
- (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ vgImage = QVGImagePool::instance()->createImageForPixmap
+ (VG_sARGB_8888_PRE, 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)
+ return VG_INVALID_HANDLE;
+
+ inImagePool = true;
+ } else if (inImagePool) {
+ QVGImagePool::instance()->useImage(this);
}
if (!source.isNull() && recreate) {
@@ -278,8 +292,17 @@ VGImage QVGPixmapData::toVGImage(qreal opacity)
// Create an alternative image for the selected opacity.
if (vgImageOpacity == VG_INVALID_HANDLE || cachedOpacity != opacity) {
if (vgImageOpacity == VG_INVALID_HANDLE) {
- vgImageOpacity = vgCreateImage
- (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ if (inImagePool) {
+ vgImageOpacity = QVGImagePool::instance()->createImageForPixmap
+ (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this);
+ } else {
+ vgImageOpacity = vgCreateImage
+ (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ }
+
+ // Bail out if we run out of GPU memory - try again next time.
+ if (vgImageOpacity == VG_INVALID_HANDLE)
+ return VG_INVALID_HANDLE;
}
VGfloat matrix[20] = {
1.0f, 0.0f, 0.0f, 0.0f,
@@ -300,6 +323,14 @@ VGImage QVGPixmapData::toVGImage(qreal opacity)
#endif
}
+void QVGPixmapData::detachImageFromPool()
+{
+ if (inImagePool) {
+ QVGImagePool::instance()->detachImage(this);
+ inImagePool = false;
+ }
+}
+
void QVGPixmapData::hibernate()
{
// If the image was imported (e.g, from an SgImage under Symbian),
@@ -311,6 +342,14 @@ void QVGPixmapData::hibernate()
destroyImageAndContext();
}
+void QVGPixmapData::reclaimImages()
+{
+ if (!inImagePool)
+ return;
+ forceToImage();
+ destroyImages();
+}
+
extern int qt_defaultDpiX();
extern int qt_defaultDpiY();
@@ -403,14 +442,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
if (!context)
context = qt_vg_create_context(0, QInternal::Pixmap);
- if (vgImage != VG_INVALID_HANDLE) {
- vgDestroyImage(vgImage);
- vgImage = VG_INVALID_HANDLE;
- }
- if (vgImageOpacity != VG_INVALID_HANDLE) {
- vgDestroyImage(vgImageOpacity);
- vgImageOpacity = VG_INVALID_HANDLE;
- }
+ destroyImages();
prevSize = QSize();
TInt err = 0;
diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h
index c0bb098..4ff95c1 100644
--- a/src/openvg/qpixmapdata_vg_p.h
+++ b/src/openvg/qpixmapdata_vg_p.h
@@ -63,6 +63,7 @@ class RSGImage;
QT_BEGIN_NAMESPACE
class QEglContext;
+class QVGImagePool;
#if !defined(QT_NO_EGL)
class QVGPixmapData;
@@ -101,6 +102,9 @@ public:
// Return the VGImage form for a specific opacity setting.
virtual VGImage toVGImage(qreal opacity);
+ // Detach this image from the image pool.
+ virtual void detachImageFromPool();
+
// Release the VG resources associated with this pixmap and copy
// the pixmap's contents out of the GPU back into main memory.
// The VG resource will be automatically recreated the next time
@@ -109,6 +113,10 @@ public:
// process via a SgImage).
virtual void hibernate();
+ // Called when the QVGImagePool wants to reclaim this pixmap's
+ // VGImage objects to reuse storage.
+ virtual void reclaimImages();
+
QSize size() const { return QSize(w, h); }
#if defined(Q_OS_SYMBIAN)
@@ -123,8 +131,13 @@ protected:
void cleanup();
#endif
-#if !defined(QT_NO_EGL)
private:
+ QVGPixmapData *nextLRU;
+ QVGPixmapData *prevLRU;
+ bool inLRU;
+ friend class QVGImagePool;
+
+#if !defined(QT_NO_EGL)
QVGPixmapData *next;
QVGPixmapData *prev;
@@ -140,6 +153,7 @@ protected:
qreal cachedOpacity;
mutable QImage source;
mutable bool recreate;
+ bool inImagePool;
#if !defined(QT_NO_EGL)
mutable QEglContext *context;
#endif
@@ -148,6 +162,7 @@ protected:
QImage::Format sourceFormat() const;
void destroyImageAndContext();
+ void destroyImages();
};
QT_END_NAMESPACE
diff --git a/src/openvg/qpixmapfilter_vg.cpp b/src/openvg/qpixmapfilter_vg.cpp
index e17c728..aa526ed 100644
--- a/src/openvg/qpixmapfilter_vg.cpp
+++ b/src/openvg/qpixmapfilter_vg.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qpixmapfilter_vg_p.h"
+#include "qvgimagepool_p.h"
#include <QtCore/qvarlengtharray.h>
#include <QtGui/qpainter.h>
@@ -82,9 +83,9 @@ void QVGPixmapConvolutionFilter::draw
return;
QSize size = pd->size();
- VGImage dstImage = vgCreateImage
+ VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
(VG_sARGB_8888_PRE, size.width(), size.height(),
- VG_IMAGE_QUALITY_FASTER);
+ VG_IMAGE_QUALITY_FASTER, pd);
if (dstImage == VG_INVALID_HANDLE)
return;
@@ -124,7 +125,7 @@ void QVGPixmapConvolutionFilter::draw
if(child != dstImage)
vgDestroyImage(child);
- vgDestroyImage(dstImage);
+ QVGImagePool::instance()->releaseImage(0, dstImage);
}
QVGPixmapColorizeFilter::QVGPixmapColorizeFilter()
@@ -155,9 +156,9 @@ void QVGPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const
return;
QSize size = pd->size();
- VGImage dstImage = vgCreateImage
+ VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
(VG_sARGB_8888_PRE, size.width(), size.height(),
- VG_IMAGE_QUALITY_FASTER);
+ VG_IMAGE_QUALITY_FASTER, pd);
if (dstImage == VG_INVALID_HANDLE)
return;
@@ -217,7 +218,7 @@ void QVGPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const
if(child != dstImage)
vgDestroyImage(child);
- vgDestroyImage(dstImage);
+ QVGImagePool::instance()->releaseImage(0, dstImage);
}
QVGPixmapDropShadowFilter::QVGPixmapDropShadowFilter()
@@ -248,9 +249,9 @@ void QVGPixmapDropShadowFilter::draw(QPainter *painter, const QPointF &dest, con
return;
QSize size = pd->size();
- VGImage dstImage = vgCreateImage
+ VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
(VG_A_8, size.width(), size.height(),
- VG_IMAGE_QUALITY_FASTER);
+ VG_IMAGE_QUALITY_FASTER, pd);
if (dstImage == VG_INVALID_HANDLE)
return;
@@ -282,7 +283,7 @@ void QVGPixmapDropShadowFilter::draw(QPainter *painter, const QPointF &dest, con
if(child != dstImage)
vgDestroyImage(child);
- vgDestroyImage(dstImage);
+ QVGImagePool::instance()->releaseImage(0, dstImage);
// Now draw the actual pixmap over the top.
painter->drawPixmap(dest, src, srect);
@@ -316,9 +317,9 @@ void QVGPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPi
return;
QSize size = pd->size();
- VGImage dstImage = vgCreateImage
+ VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
(VG_sARGB_8888_PRE, size.width(), size.height(),
- VG_IMAGE_QUALITY_FASTER);
+ VG_IMAGE_QUALITY_FASTER, pd);
if (dstImage == VG_INVALID_HANDLE)
return;
@@ -347,7 +348,7 @@ void QVGPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPi
if(child != dstImage)
vgDestroyImage(child);
- vgDestroyImage(dstImage);
+ QVGImagePool::instance()->releaseImage(0, dstImage);
}
#endif
diff --git a/src/openvg/qvgimagepool.cpp b/src/openvg/qvgimagepool.cpp
new file mode 100644
index 0000000..93e6e03
--- /dev/null
+++ b/src/openvg/qvgimagepool.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenVG module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvgimagepool_p.h"
+#include "qpixmapdata_vg_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QVGImagePool *qt_vg_image_pool = 0;
+
+class QVGImagePoolPrivate
+{
+public:
+ QVGImagePoolPrivate() : lruFirst(0), lruLast(0) {}
+
+ QVGPixmapData *lruFirst;
+ QVGPixmapData *lruLast;
+};
+
+QVGImagePool::QVGImagePool()
+ : d_ptr(new QVGImagePoolPrivate())
+{
+}
+
+QVGImagePool::~QVGImagePool()
+{
+}
+
+QVGImagePool *QVGImagePool::instance()
+{
+ if (!qt_vg_image_pool)
+ qt_vg_image_pool = new QVGImagePool();
+ return qt_vg_image_pool;
+}
+
+void QVGImagePool::setImagePool(QVGImagePool *pool)
+{
+ if (qt_vg_image_pool != pool)
+ delete qt_vg_image_pool;
+ qt_vg_image_pool = pool;
+}
+
+VGImage QVGImagePool::createTemporaryImage(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality,
+ QVGPixmapData *keepData)
+{
+ VGImage image;
+ do {
+ image = vgCreateImage(format, width, height, allowedQuality);
+ if (image != VG_INVALID_HANDLE)
+ return image;
+ } while (reclaimSpace(format, width, height, keepData));
+ qWarning("QVGImagePool: cannot reclaim sufficient space for a %dx%d temporary image",
+ width, height);
+ return VG_INVALID_HANDLE;
+}
+
+VGImage QVGImagePool::createImageForPixmap(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality,
+ QVGPixmapData *data)
+{
+ VGImage image;
+ do {
+ image = vgCreateImage(format, width, height, allowedQuality);
+ if (image != VG_INVALID_HANDLE) {
+ if (data)
+ moveToHeadOfLRU(data);
+ return image;
+ }
+ } while (reclaimSpace(format, width, height, data));
+ qWarning("QVGImagePool: cannot reclaim sufficient space for a %dx%d pixmap",
+ width, height);
+ return VG_INVALID_HANDLE;
+}
+
+VGImage QVGImagePool::createPermanentImage(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality)
+{
+ VGImage image;
+ do {
+ image = vgCreateImage(format, width, height, allowedQuality);
+ if (image != VG_INVALID_HANDLE)
+ return image;
+ } while (reclaimSpace(format, width, height, 0));
+ qWarning("QVGImagePool: cannot reclaim sufficient space for a %dx%d image",
+ width, height);
+ return VG_INVALID_HANDLE;
+}
+
+void QVGImagePool::releaseImage(QVGPixmapData *data, VGImage image)
+{
+ // Very simple strategy at the moment: just destroy the image.
+ if (data)
+ removeFromLRU(data);
+ vgDestroyImage(image);
+}
+
+void QVGImagePool::useImage(QVGPixmapData *data)
+{
+ moveToHeadOfLRU(data);
+}
+
+void QVGImagePool::detachImage(QVGPixmapData *data)
+{
+ removeFromLRU(data);
+}
+
+bool QVGImagePool::reclaimSpace(VGImageFormat format,
+ VGint width, VGint height,
+ QVGPixmapData *data)
+{
+ Q_UNUSED(format); // For future use in picking the best image to eject.
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+
+ if (data)
+ moveToHeadOfLRU(data);
+
+ QVGPixmapData *lrudata = pixmapLRU();
+ if (lrudata && lrudata != data) {
+ lrudata->reclaimImages();
+ return true;
+ }
+
+ return false;
+}
+
+void QVGImagePool::hibernate()
+{
+ // Nothing to do here at the moment since the pool does not
+ // retain VGImage's after they have been released.
+}
+
+void QVGImagePool::moveToHeadOfLRU(QVGPixmapData *data)
+{
+ Q_D(QVGImagePool);
+ if (data->inLRU) {
+ if (!data->prevLRU)
+ return; // Already at the head of the list.
+ removeFromLRU(data);
+ }
+ data->inLRU = true;
+ data->nextLRU = d->lruFirst;
+ data->prevLRU = 0;
+ if (d->lruFirst)
+ d->lruFirst->prevLRU = data;
+ else
+ d->lruLast = data;
+ d->lruFirst = data;
+}
+
+void QVGImagePool::removeFromLRU(QVGPixmapData *data)
+{
+ Q_D(QVGImagePool);
+ if (!data->inLRU)
+ return;
+ if (data->nextLRU)
+ data->nextLRU->prevLRU = data->prevLRU;
+ else
+ d->lruLast = data->prevLRU;
+ if (data->prevLRU)
+ data->prevLRU->nextLRU = data->nextLRU;
+ else
+ d->lruFirst = data->nextLRU;
+ data->inLRU = false;
+}
+
+QVGPixmapData *QVGImagePool::pixmapLRU()
+{
+ Q_D(QVGImagePool);
+ return d->lruLast;
+}
+
+QT_END_NAMESPACE
diff --git a/src/openvg/qvgimagepool_p.h b/src/openvg/qvgimagepool_p.h
new file mode 100644
index 0000000..66a4998
--- /dev/null
+++ b/src/openvg/qvgimagepool_p.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenVG module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVGIMAGEPOOL_P_H
+#define QVGIMAGEPOOL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qvg.h"
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVGPixmapData;
+class QVGImagePoolPrivate;
+
+class Q_OPENVG_EXPORT QVGImagePool
+{
+public:
+ QVGImagePool();
+ virtual ~QVGImagePool();
+
+ static QVGImagePool *instance();
+
+ // This function can be used from system-specific graphics system
+ // plugins to alter the image allocation strategy.
+ static void setImagePool(QVGImagePool *pool);
+
+ // Create a new VGImage from the pool with the specified parameters
+ // that is not associated with a pixmap. The VGImage is returned to
+ // the pool when releaseImage() is called.
+ //
+ // This function will call reclaimSpace() when vgCreateImage() fails.
+ //
+ // This function is typically called when allocating temporary
+ // VGImage's for pixmap filters. The "keepData" object will not
+ // be reclaimed if reclaimSpace() needs to be called.
+ virtual VGImage createTemporaryImage(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality,
+ QVGPixmapData *keepData = 0);
+
+ // Create a new VGImage with the specified parameters and associate
+ // it with "data". The QVGPixmapData will be notified when the
+ // VGImage needs to be reclaimed by the pool.
+ //
+ // This function will call reclaimSpace() when vgCreateImage() fails.
+ virtual VGImage createImageForPixmap(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality,
+ QVGPixmapData *data);
+
+ // Create a permanent VGImage with the specified parameters.
+ // If there is insufficient space for the vgCreateImage call,
+ // then this function will call reclaimSpace() and try again.
+ //
+ // The caller is responsible for calling vgDestroyImage()
+ // when it no longer needs the VGImage, as the image is not
+ // recorded in the image pool.
+ //
+ // This function is typically used for pattern brushes where
+ // the OpenVG engine is responsible for managing the lifetime
+ // of the VGImage, destroying it automatically when the brush
+ // is no longer in use.
+ virtual VGImage createPermanentImage(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality);
+
+ // Release a VGImage that is no longer required.
+ virtual void releaseImage(QVGPixmapData *data, VGImage image);
+
+ // Notify the pool that a QVGPixmapData object is using
+ // an image again. This allows the pool to move the image
+ // within a least-recently-used list of QVGPixmapData objects.
+ virtual void useImage(QVGPixmapData *data);
+
+ // Notify the pool that the VGImage's associated with a
+ // QVGPixmapData are being detached from the pool. The caller
+ // will become responsible for calling vgDestroyImage().
+ virtual void detachImage(QVGPixmapData *data);
+
+ // Reclaim space for an image allocation with the specified parameters.
+ // Returns true if space was reclaimed, or false if there is no
+ // further space that can be reclaimed. The "data" parameter
+ // indicates the pixmap that is trying to obtain space which should
+ // not itself be reclaimed.
+ virtual bool reclaimSpace(VGImageFormat format,
+ VGint width, VGint height,
+ QVGPixmapData *data);
+
+ // Hibernate the image pool because the context is about to be
+ // destroyed. All VGImage's left in the pool should be released.
+ virtual void hibernate();
+
+protected:
+ // Helper functions for managing the LRU list of QVGPixmapData objects.
+ void moveToHeadOfLRU(QVGPixmapData *data);
+ void removeFromLRU(QVGPixmapData *data);
+ QVGPixmapData *pixmapLRU();
+
+private:
+ QScopedPointer<QVGImagePoolPrivate> d_ptr;
+
+ Q_DECLARE_PRIVATE(QVGImagePool)
+ Q_DISABLE_COPY(QVGImagePool)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp
index 1571083..bda6096 100644
--- a/src/openvg/qwindowsurface_vgegl.cpp
+++ b/src/openvg/qwindowsurface_vgegl.cpp
@@ -42,6 +42,7 @@
#include "qwindowsurface_vgegl_p.h"
#include "qpaintengine_vg_p.h"
#include "qpixmapdata_vg_p.h"
+#include "qvgimagepool_p.h"
#include "qvg_p.h"
#if !defined(QT_NO_EGL)
@@ -360,6 +361,9 @@ void qt_vg_hibernate_pixmaps(QVGSharedContext *shared)
pd = pd->next;
}
+ // Hibernate any remaining VGImage's in the image pool.
+ QVGImagePool::instance()->hibernate();
+
// Don't need the current context any more.
shared->context->lazyDoneCurrent();