/******************************************************************************** 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_NAMESPACEstatic 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