summaryrefslogtreecommitdiffstats
path: root/src/openvg
diff options
context:
space:
mode:
authorRohan McGovern <rohan.mcgovern@nokia.com>2010-02-01 05:53:18 (GMT)
committerRohan McGovern <rohan.mcgovern@nokia.com>2010-02-01 05:53:18 (GMT)
commit4915439de467d1119a46af66ea08dbe161d2f336 (patch)
tree450a989691b5a892b07d5edbe5cf88ba78d388a0 /src/openvg
parent5bda4e27bbe3fde98bd5c628fada76dfccadad0e (diff)
parent4d1c8407c1ac16b6288c3aa0f7c2118d2748f348 (diff)
downloadQt-4915439de467d1119a46af66ea08dbe161d2f336.zip
Qt-4915439de467d1119a46af66ea08dbe161d2f336.tar.gz
Qt-4915439de467d1119a46af66ea08dbe161d2f336.tar.bz2
Merge commit 'origin/4.6' into oslo1-master
Conflicts: doc/src/deployment/deployment.qdoc doc/src/getting-started/installation.qdoc examples/assistant/simpletextviewer/findfiledialog.cpp examples/assistant/simpletextviewer/findfiledialog.h examples/assistant/simpletextviewer/mainwindow.cpp examples/webkit/fancybrowser/main.cpp src/corelib/global/qglobal.h src/gui/dialogs/qfiledialog_win.cpp src/plugins/qpluginbase.pri src/qbase.pri tests/auto/selftests/expected_cmptest.txt tests/auto/selftests/expected_crashes_3.txt tests/auto/selftests/expected_longstring.txt tests/auto/selftests/expected_maxwarnings.txt tests/auto/selftests/expected_skip.txt tools/assistant/compat/config.cpp tools/assistant/compat/config.h tools/assistant/compat/docuparser.cpp tools/assistant/compat/docuparser.h tools/assistant/compat/fontsettingsdialog.cpp tools/assistant/compat/helpdialog.cpp tools/assistant/compat/helpdialog.h tools/assistant/compat/helpdialog.ui tools/assistant/compat/helpwindow.cpp tools/assistant/compat/helpwindow.h tools/assistant/compat/index.cpp tools/assistant/compat/index.h tools/assistant/compat/lib/qassistantclient.cpp tools/assistant/compat/lib/qassistantclient.h tools/assistant/compat/main.cpp tools/assistant/compat/mainwindow.cpp tools/assistant/compat/mainwindow.h tools/assistant/compat/mainwindow.ui tools/assistant/compat/profile.cpp tools/assistant/compat/profile.h tools/assistant/compat/tabbedbrowser.cpp tools/assistant/compat/tabbedbrowser.h tools/assistant/compat/tabbedbrowser.ui tools/assistant/compat/topicchooser.cpp tools/assistant/compat/topicchooser.ui tools/assistant/lib/qhelpsearchquerywidget.cpp tools/assistant/tools/assistant/centralwidget.cpp tools/assistant/tools/assistant/doc/assistant.qdocconf tools/assistant/tools/assistant/helpviewer.cpp tools/linguist/lupdate/main.cpp tools/qdoc3/test/assistant.qdocconf tools/qdoc3/test/designer.qdocconf tools/qdoc3/test/linguist.qdocconf tools/qdoc3/test/qmake.qdocconf tools/qdoc3/test/qt-build-docs.qdocconf tools/qdoc3/test/qt.qdocconf
Diffstat (limited to 'src/openvg')
-rw-r--r--src/openvg/openvg.pro7
-rw-r--r--src/openvg/qpaintengine_vg.cpp69
-rw-r--r--src/openvg/qpaintengine_vg_p.h2
-rw-r--r--src/openvg/qpixmapdata_vg.cpp133
-rw-r--r--src/openvg/qpixmapdata_vg_p.h48
-rw-r--r--src/openvg/qpixmapfilter_vg.cpp27
-rw-r--r--src/openvg/qpixmapfilter_vg_p.h2
-rw-r--r--src/openvg/qvg.h2
-rw-r--r--src/openvg/qvg_p.h12
-rw-r--r--src/openvg/qvgcompositionhelper_p.h6
-rw-r--r--src/openvg/qvgimagepool.cpp215
-rw-r--r--src/openvg/qvgimagepool_p.h157
-rw-r--r--src/openvg/qwindowsurface_vg.cpp2
-rw-r--r--src/openvg/qwindowsurface_vg_p.h2
-rw-r--r--src/openvg/qwindowsurface_vgegl.cpp172
-rw-r--r--src/openvg/qwindowsurface_vgegl_p.h2
16 files changed, 733 insertions, 125 deletions
diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro
index bf224b4..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 += \
@@ -34,6 +36,7 @@ contains(QT_CONFIG, egl) {
include(../qbase.pri)
unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui
+symbian:TARGET.UID3 = 0x2001E62F
!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG
!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS_PRIVATE += -L$$QMAKE_LIBDIR_OPENVG
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index fda4b10..cc9ba77 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -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"
@@ -199,6 +200,7 @@ public:
QRegion scissorRegion; // Currently active scissor region.
bool scissorActive; // True if scissor region is active.
+ bool scissorDirty; // True if scissor is dirty after native painting.
QPaintEngine::DirtyFlags dirty;
@@ -356,6 +358,7 @@ void QVGPaintEnginePrivate::init()
rawVG = false;
scissorActive = false;
+ scissorDirty = false;
dirty = 0;
@@ -983,6 +986,9 @@ static QImage colorizeBitmap(const QImage &image, const QColor &color)
return dest;
}
+// defined in qpixmapdata_vg.cpp.
+const uchar *qt_vg_imageBits(const QImage& image);
+
static VGImage toVGImage
(const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
{
@@ -1016,9 +1022,9 @@ static VGImage toVGImage
break;
}
- const uchar *pixels = img.bits();
+ const uchar *pixels = qt_vg_imageBits(img);
- 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,
@@ -1060,10 +1066,10 @@ static VGImage toVGImageSubRect
break;
}
- const uchar *pixels = img.bits() + bpp * sr.x() +
+ const uchar *pixels = qt_vg_imageBits(img) + 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,
@@ -1082,9 +1088,9 @@ static VGImage toVGImageWithOpacity(const QImage & image, qreal opacity)
painter.drawImage(0, 0, image);
painter.end();
- const uchar *pixels = img.bits();
+ const uchar *pixels = qt_vg_imageBits(img);
- 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,
@@ -1104,9 +1110,9 @@ static VGImage toVGImageWithOpacitySubRect
painter.drawImage(QPoint(0, 0), image, sr);
painter.end();
- const uchar *pixels = img.bits();
+ const uchar *pixels = qt_vg_imageBits(img);
- 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 +1200,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 +1213,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;
@@ -1570,12 +1583,6 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
d->dirty |= QPaintEngine::DirtyClipRegion;
- // If we have a non-simple transform, then use path-based clipping.
- if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) {
- QPaintEngineEx::clip(rect, op);
- return;
- }
-
switch (op) {
case Qt::NoClip:
{
@@ -1612,12 +1619,6 @@ void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
d->dirty |= QPaintEngine::DirtyClipRegion;
- // If we have a non-simple transform, then use path-based clipping.
- if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) {
- QPaintEngineEx::clip(region, op);
- return;
- }
-
switch (op) {
case Qt::NoClip:
{
@@ -2087,6 +2088,7 @@ void QVGPaintEngine::updateScissor()
// so there is no point doing any scissoring.
vgSeti(VG_SCISSORING, VG_FALSE);
d->scissorActive = false;
+ d->scissorDirty = false;
return;
}
} else
@@ -2104,6 +2106,7 @@ void QVGPaintEngine::updateScissor()
// so there is no point doing any scissoring.
vgSeti(VG_SCISSORING, VG_FALSE);
d->scissorActive = false;
+ d->scissorDirty = false;
return;
}
} else
@@ -2113,11 +2116,12 @@ void QVGPaintEngine::updateScissor()
if (region.isEmpty()) {
vgSeti(VG_SCISSORING, VG_FALSE);
d->scissorActive = false;
+ d->scissorDirty = false;
return;
}
}
- if (d->scissorActive && region == d->scissorRegion)
+ if (d->scissorActive && region == d->scissorRegion && !d->scissorDirty)
return;
QVector<QRect> rects = region.rects();
@@ -2135,6 +2139,7 @@ void QVGPaintEngine::updateScissor()
vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
vgSeti(VG_SCISSORING, VG_TRUE);
+ d->scissorDirty = false;
d->scissorActive = true;
d->scissorRegion = region;
}
@@ -3170,15 +3175,15 @@ void QVGFontGlyphCache::cacheGlyphs
if (!scaledImage.isNull()) { // Not a space character
if (scaledImage.format() == QImage::Format_Indexed8) {
vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
- vgImageSubData(vgImage, scaledImage.bits(), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
+ vgImageSubData(vgImage, qt_vg_imageBits(scaledImage), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
} else if (scaledImage.format() == QImage::Format_Mono) {
QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
- vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
+ vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
} else {
QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
- vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
+ vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
}
}
origin[0] = -metrics.x.toReal() + 0.5f;
@@ -3337,6 +3342,7 @@ void QVGPaintEngine::endNativePainting()
d->brushType = (VGPaintType)0;
d->clearColor = QColor();
d->fillPaint = d->brushPaint;
+ d->scissorDirty = true;
restoreState(QPaintEngine::AllDirty);
d->dirty = dirty;
d->rawVG = false;
@@ -3459,14 +3465,11 @@ void QVGCompositionHelper::endCompositing()
}
void QVGCompositionHelper::blitWindow
- (QVGEGLWindowSurfacePrivate *surface, const QRect& rect,
- const QPoint& topLeft, int opacity)
+ (VGImage image, const QSize& imageSize,
+ const QRect& rect, const QPoint& topLeft, int opacity)
{
- // Get the VGImage that is acting as a back buffer for the window.
- VGImage image = surface->surfaceImage();
if (image == VG_INVALID_HANDLE)
return;
- QSize imageSize = surface->surfaceSize();
// Determine which sub rectangle of the window to draw.
QRect sr = rect.translated(-topLeft);
@@ -3647,7 +3650,7 @@ void QVGCompositionHelper::drawCursorPixmap
if (vgImage == VG_INVALID_HANDLE)
return;
vgImageSubData
- (vgImage, img.bits() + img.bytesPerLine() * (img.height() - 1),
+ (vgImage, qt_vg_imageBits(img) + img.bytesPerLine() * (img.height() - 1),
-(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
img.width(), img.height());
@@ -3673,15 +3676,17 @@ void QVGCompositionHelper::setScissor(const QRegion& region)
vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
vgSeti(VG_SCISSORING, VG_TRUE);
+ d->scissorDirty = false;
d->scissorActive = true;
d->scissorRegion = region;
}
void QVGCompositionHelper::clearScissor()
{
- if (d->scissorActive) {
+ if (d->scissorActive || d->scissorDirty) {
vgSeti(VG_SCISSORING, VG_FALSE);
d->scissorActive = false;
+ d->scissorDirty = false;
}
}
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
index 86a522a..3f87a72 100644
--- a/src/openvg/qpaintengine_vg_p.h
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index 19c90ed..cc0e5a1 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -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,41 +64,68 @@ 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);
#endif
setSerialNumber(++qt_vg_pixmap_serial);
}
QVGPixmapData::~QVGPixmapData()
{
+ destroyImageAndContext();
+#if !defined(QT_NO_EGL)
+ qt_vg_unregister_pixmap(this);
+#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
}
#if !defined(QT_NO_EGL)
- if (context)
- qt_vg_destroy_context(context);
+ if (context) {
+ qt_vg_destroy_context(context, QInternal::Pixmap);
+ context = 0;
+ }
#endif
+ recreate = true;
}
QPixmapData *QVGPixmapData::createCompatiblePixmapData() const
@@ -204,7 +232,7 @@ QPaintEngine* QVGPixmapData::paintEngine() const
// This function works around QImage::bits() making a deep copy if the
// QImage is not const. We force it to be const and then get the bits.
// XXX: Should add a QImage::constBits() in the future to replace this.
-static inline const uchar *qt_vg_imageBits(const QImage& image)
+const uchar *qt_vg_imageBits(const QImage& image)
{
return image.bits();
}
@@ -217,25 +245,25 @@ VGImage QVGPixmapData::toVGImage()
#if !defined(QT_NO_EGL)
// Increase the reference count on the shared context.
if (!context)
- context = qt_vg_create_context(0);
+ 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) {
@@ -264,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,
@@ -286,6 +323,33 @@ 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),
+ // then we cannot copy it back to main memory for storage.
+ if (vgImage != VG_INVALID_HANDLE && source.isNull())
+ return;
+
+ forceToImage();
+ destroyImageAndContext();
+}
+
+void QVGPixmapData::reclaimImages()
+{
+ if (!inImagePool)
+ return;
+ forceToImage();
+ destroyImages();
+}
+
extern int qt_defaultDpiX();
extern int qt_defaultDpiY();
@@ -376,16 +440,9 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
// when "0" used as argument then
// default display, context are used
if (!context)
- context = qt_vg_create_context(0);
+ 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 fe19f35..c21b48f 100644
--- a/src/openvg/qpixmapdata_vg_p.h
+++ b/src/openvg/qpixmapdata_vg_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -55,8 +55,6 @@
#include <QtGui/private/qpixmap_raster_p.h>
#include <private/qvg_p.h>
-#if !defined(QT_NO_EGL)
-#endif
#if defined(Q_OS_SYMBIAN)
class RSGImage;
@@ -65,6 +63,16 @@ class RSGImage;
QT_BEGIN_NAMESPACE
class QEglContext;
+class QVGImagePool;
+
+#if !defined(QT_NO_EGL)
+class QVGPixmapData;
+class QVGSharedContext;
+
+void qt_vg_register_pixmap(QVGPixmapData *pd);
+void qt_vg_unregister_pixmap(QVGPixmapData *pd);
+void qt_vg_hibernate_pixmaps(QVGSharedContext *context);
+#endif
class Q_OPENVG_EXPORT QVGPixmapData : public QPixmapData
{
@@ -94,6 +102,21 @@ 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
+ // toVGImage() is called. Does nothing if the pixmap cannot be
+ // hibernated for some reason (e.g. VGImage is shared with another
+ // 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)
@@ -108,6 +131,21 @@ protected:
void cleanup();
#endif
+private:
+ QVGPixmapData *nextLRU;
+ QVGPixmapData *prevLRU;
+ bool inLRU;
+ friend class QVGImagePool;
+
+#if !defined(QT_NO_EGL)
+ QVGPixmapData *next;
+ QVGPixmapData *prev;
+
+ friend void qt_vg_register_pixmap(QVGPixmapData *pd);
+ friend void qt_vg_unregister_pixmap(QVGPixmapData *pd);
+ friend void qt_vg_hibernate_pixmaps(QVGSharedContext *context);
+#endif
+
protected:
QSize prevSize;
VGImage vgImage;
@@ -115,12 +153,16 @@ protected:
qreal cachedOpacity;
mutable QImage source;
mutable bool recreate;
+ bool inImagePool;
#if !defined(QT_NO_EGL)
mutable QEglContext *context;
#endif
void forceToImage();
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..1ea1f55 100644
--- a/src/openvg/qpixmapfilter_vg.cpp
+++ b/src/openvg/qpixmapfilter_vg.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -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/qpixmapfilter_vg_p.h b/src/openvg/qpixmapfilter_vg_p.h
index 29dd37e..b6a1f61 100644
--- a/src/openvg/qpixmapfilter_vg_p.h
+++ b/src/openvg/qpixmapfilter_vg_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/openvg/qvg.h b/src/openvg/qvg.h
index ff5b04c..962d789 100644
--- a/src/openvg/qvg.h
+++ b/src/openvg/qvg.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/openvg/qvg_p.h b/src/openvg/qvg_p.h
index 04e2bab..7857bb6 100644
--- a/src/openvg/qvg_p.h
+++ b/src/openvg/qvg_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -71,11 +71,17 @@ class QEglContext;
// Create an EGL context, but don't bind it to a surface. If single-context
// mode is enabled, this will return the previously-created context.
-Q_OPENVG_EXPORT QEglContext *qt_vg_create_context(QPaintDevice *device);
+// "devType" indicates the type of device using the context, usually
+// QInternal::Widget or QInternal::Pixmap.
+Q_OPENVG_EXPORT QEglContext *qt_vg_create_context
+ (QPaintDevice *device, int devType);
// Destroy an EGL context that was created by qt_vg_create_context().
// If single-context mode is enabled, this will decrease the reference count.
-Q_OPENVG_EXPORT void qt_vg_destroy_context(QEglContext *context);
+// "devType" indicates the type of device destroying the context, usually
+// QInternal::Widget or QInternal::Pixmap.
+Q_OPENVG_EXPORT void qt_vg_destroy_context
+ (QEglContext *context, int devType);
// Return the shared pbuffer surface that can be made current to
// destroy VGImage objects when there is no other surface available.
diff --git a/src/openvg/qvgcompositionhelper_p.h b/src/openvg/qvgcompositionhelper_p.h
index 3afe31e..366fe12 100644
--- a/src/openvg/qvgcompositionhelper_p.h
+++ b/src/openvg/qvgcompositionhelper_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -71,8 +71,8 @@ public:
void startCompositing(const QSize& screenSize);
void endCompositing();
- void blitWindow(QVGEGLWindowSurfacePrivate *surface, const QRect& rect,
- const QPoint& topLeft, int opacity);
+ void blitWindow(VGImage image, const QSize& imageSize,
+ const QRect& rect, const QPoint& topLeft, int opacity);
void fillBackground(const QRegion& region, const QBrush& brush);
void drawCursorPixmap(const QPixmap& pixmap, const QPoint& offset);
void setScissor(const QRegion& region);
diff --git a/src/openvg/qvgimagepool.cpp b/src/openvg/qvgimagepool.cpp
new file mode 100644
index 0000000..78277aa
--- /dev/null
+++ b/src/openvg/qvgimagepool.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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..d61476d
--- /dev/null
+++ b/src/openvg/qvgimagepool_p.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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_vg.cpp b/src/openvg/qwindowsurface_vg.cpp
index a1301e3..83b0764 100644
--- a/src/openvg/qwindowsurface_vg.cpp
+++ b/src/openvg/qwindowsurface_vg.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/openvg/qwindowsurface_vg_p.h b/src/openvg/qwindowsurface_vg_p.h
index b149625..93fb5a7 100644
--- a/src/openvg/qwindowsurface_vg_p.h
+++ b/src/openvg/qwindowsurface_vg_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp
index 29d82c8..d92870f 100644
--- a/src/openvg/qwindowsurface_vgegl.cpp
+++ b/src/openvg/qwindowsurface_vgegl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -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)
@@ -111,15 +112,19 @@ public:
QEglContext *context;
int refCount;
+ int widgetRefCount;
QVGPaintEngine *engine;
EGLSurface surface;
+ QVGPixmapData *firstPixmap;
};
QVGSharedContext::QVGSharedContext()
: context(0)
, refCount(0)
+ , widgetRefCount(0)
, engine(0)
, surface(EGL_NO_SURFACE)
+ , firstPixmap(0)
{
}
@@ -154,6 +159,28 @@ void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
Q_UNUSED(engine);
}
+void qt_vg_register_pixmap(QVGPixmapData *pd)
+{
+ QVGSharedContext *shared = sharedContext();
+ pd->next = shared->firstPixmap;
+ pd->prev = 0;
+ if (shared->firstPixmap)
+ shared->firstPixmap->prev = pd;
+ shared->firstPixmap = pd;
+}
+
+void qt_vg_unregister_pixmap(QVGPixmapData *pd)
+{
+ if (pd->next)
+ pd->next->prev = pd->prev;
+ if (pd->prev) {
+ pd->prev->next = pd->next;
+ } else {
+ QVGSharedContext *shared = sharedContext();
+ shared->firstPixmap = pd->next;
+ }
+}
+
#else
QVGPaintEngine *qt_vg_create_paint_engine(void)
@@ -166,6 +193,16 @@ void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
delete engine;
}
+void qt_vg_register_pixmap(QVGPixmapData *pd)
+{
+ Q_UNUSED(pd);
+}
+
+void qt_vg_unregister_pixmap(QVGPixmapData *pd)
+{
+ Q_UNUSED(pd);
+}
+
#endif
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
@@ -200,6 +237,42 @@ static QEglContext *createContext(QPaintDevice *device)
else
eglSwapInterval(context->display(), 1);
+#ifdef EGL_RENDERABLE_TYPE
+ // Has the user specified an explicit EGL configuration to use?
+ QByteArray configId = qgetenv("QT_VG_EGL_CONFIG");
+ if (!configId.isEmpty()) {
+ EGLint cfgId = configId.toInt();
+ EGLint properties[] = {
+ EGL_CONFIG_ID, cfgId,
+ EGL_NONE
+ };
+ EGLint matching = 0;
+ EGLConfig cfg;
+ if (eglChooseConfig
+ (context->display(), properties, &cfg, 1, &matching) &&
+ matching > 0) {
+ // Check that the selected configuration actually supports OpenVG
+ // and then create the context with it.
+ EGLint id = 0;
+ EGLint type = 0;
+ eglGetConfigAttrib
+ (context->display(), cfg, EGL_CONFIG_ID, &id);
+ eglGetConfigAttrib
+ (context->display(), cfg, EGL_RENDERABLE_TYPE, &type);
+ if (cfgId == id && (type & EGL_OPENVG_BIT) != 0) {
+ context->setConfig(cfg);
+ if (!context->createContext()) {
+ delete context;
+ return 0;
+ }
+ return context;
+ } else {
+ qWarning("QT_VG_EGL_CONFIG: %d is not a valid OpenVG configuration", int(cfgId));
+ }
+ }
+ }
+#endif
+
// Choose an appropriate configuration for rendering into the device.
QEglProperties configProps;
configProps.setPaintDeviceFormat(device);
@@ -211,19 +284,19 @@ static QEglContext *createContext(QPaintDevice *device)
configProps.setValue(EGL_ALPHA_MASK_SIZE, 1);
#endif
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
- configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT |
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
EGL_VG_ALPHA_FORMAT_PRE_BIT);
configProps.setRenderableType(QEgl::OpenVG);
if (!context->chooseConfig(configProps)) {
// Try again without the "pre" bit.
- configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
if (!context->chooseConfig(configProps)) {
delete context;
return 0;
}
}
#else
- configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
configProps.setRenderableType(QEgl::OpenVG);
if (!context->chooseConfig(configProps)) {
delete context;
@@ -242,9 +315,11 @@ static QEglContext *createContext(QPaintDevice *device)
#if !defined(QVG_NO_SINGLE_CONTEXT)
-QEglContext *qt_vg_create_context(QPaintDevice *device)
+QEglContext *qt_vg_create_context(QPaintDevice *device, int devType)
{
QVGSharedContext *shared = sharedContext();
+ if (devType == QInternal::Widget)
+ ++(shared->widgetRefCount);
if (shared->context) {
++(shared->refCount);
return shared->context;
@@ -255,23 +330,68 @@ QEglContext *qt_vg_create_context(QPaintDevice *device)
}
}
-void qt_vg_destroy_context(QEglContext *context)
+static void qt_vg_destroy_shared_context(QVGSharedContext *shared)
+{
+ shared->context->makeCurrent(qt_vg_shared_surface());
+ delete shared->engine;
+ shared->engine = 0;
+ shared->context->doneCurrent();
+ if (shared->surface != EGL_NO_SURFACE) {
+ eglDestroySurface(shared->context->display(), shared->surface);
+ shared->surface = EGL_NO_SURFACE;
+ }
+ delete shared->context;
+ shared->context = 0;
+}
+
+void qt_vg_hibernate_pixmaps(QVGSharedContext *shared)
+{
+ // Artificially increase the reference count to prevent the
+ // context from being destroyed until after we have finished
+ // the hibernation process.
+ ++(shared->refCount);
+
+ // We need a context current to hibernate the VGImage objects.
+ shared->context->makeCurrent(qt_vg_shared_surface());
+
+ // Scan all QVGPixmapData objects in the system and hibernate them.
+ QVGPixmapData *pd = shared->firstPixmap;
+ while (pd != 0) {
+ pd->hibernate();
+ 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();
+
+ // Decrease the reference count and destroy the context if necessary.
+ if (--(shared->refCount) <= 0)
+ qt_vg_destroy_shared_context(shared);
+}
+
+void qt_vg_destroy_context(QEglContext *context, int devType)
{
QVGSharedContext *shared = sharedContext();
if (shared->context != context) {
// This is not the shared context. Shouldn't happen!
delete context;
- } else if (--(shared->refCount) <= 0) {
- shared->context->makeCurrent(qt_vg_shared_surface());
- delete shared->engine;
- shared->engine = 0;
- shared->context->doneCurrent();
- if (shared->surface != EGL_NO_SURFACE) {
- eglDestroySurface(shared->context->display(), shared->surface);
- shared->surface = EGL_NO_SURFACE;
- }
- delete shared->context;
- shared->context = 0;
+ return;
+ }
+ if (devType == QInternal::Widget)
+ --(shared->widgetRefCount);
+ if (--(shared->refCount) <= 0) {
+ qt_vg_destroy_shared_context(shared);
+ } else if (shared->widgetRefCount <= 0 && devType == QInternal::Widget) {
+ // All of the widget window surfaces have been destroyed
+ // but we still have VG pixmaps active. Ask them to hibernate
+ // to free up GPU resources until a widget is shown again.
+ // This may eventually cause the EGLContext to be destroyed
+ // because nothing in the system needs a context, which will
+ // free up even more GPU resources.
+ qt_vg_hibernate_pixmaps(shared);
}
}
@@ -302,13 +422,15 @@ EGLSurface qt_vg_shared_surface(void)
#else
-QEglContext *qt_vg_create_context(QPaintDevice *device)
+QEglContext *qt_vg_create_context(QPaintDevice *device, int devType)
{
+ Q_UNUSED(devType);
return createContext(device);
}
-void qt_vg_destroy_context(QEglContext *context)
+void qt_vg_destroy_context(QEglContext *context, int devType)
{
+ Q_UNUSED(devType);
delete context;
}
@@ -398,7 +520,7 @@ QVGEGLWindowSurfaceVGImage::~QVGEGLWindowSurfaceVGImage()
}
if (windowSurface != EGL_NO_SURFACE)
context->destroySurface(windowSurface);
- qt_vg_destroy_context(context);
+ qt_vg_destroy_context(context, QInternal::Widget);
}
}
@@ -417,7 +539,7 @@ QEglContext *QVGEGLWindowSurfaceVGImage::ensureContext(QWidget *widget)
if (!context) {
// Create a new EGL context. We create the surface in beginPaint().
size = newSize;
- context = qt_vg_create_context(widget);
+ context = qt_vg_create_context(widget, QInternal::Widget);
if (!context)
return 0;
isPaintingActive = false;
@@ -512,7 +634,7 @@ QVGEGLWindowSurfaceDirect::~QVGEGLWindowSurfaceDirect()
if (context) {
if (windowSurface != EGL_NO_SURFACE)
context->destroySurface(windowSurface);
- qt_vg_destroy_context(context);
+ qt_vg_destroy_context(context, QInternal::Widget);
}
}
@@ -551,7 +673,7 @@ QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
qt_vg_destroy_paint_engine(engine);
engine = 0;
context->destroySurface(windowSurface);
- qt_vg_destroy_context(context);
+ qt_vg_destroy_context(context, QInternal::Widget);
context = 0;
windowSurface = EGL_NO_SURFACE;
}
@@ -560,7 +682,7 @@ QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
if (!context) {
// Create a new EGL context and bind it to the widget surface.
size = newSize;
- context = qt_vg_create_context(widget);
+ context = qt_vg_create_context(widget, QInternal::Widget);
if (!context)
return 0;
// We want a direct to window rendering surface if possible.
@@ -577,7 +699,7 @@ QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
#endif
EGLSurface surface = context->createSurface(widget, &surfaceProps);
if (surface == EGL_NO_SURFACE) {
- qt_vg_destroy_context(context);
+ qt_vg_destroy_context(context, QInternal::Widget);
context = 0;
return 0;
}
diff --git a/src/openvg/qwindowsurface_vgegl_p.h b/src/openvg/qwindowsurface_vgegl_p.h
index 7fa60ea..aa0c648 100644
--- a/src/openvg/qwindowsurface_vgegl_p.h
+++ b/src/openvg/qwindowsurface_vgegl_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**