diff -r 000000000000 -r 16d8024aca5e src/hbservers/hbthemeserver/hbicondatacache_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbservers/hbthemeserver/hbicondatacache_p.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,967 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (developer.feedback@nokia.com) +** +** This file is part of the HbServers module of the UI Extensions for Mobile. +** +** GNU Lesser General Public License Usage +** 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 developer.feedback@nokia.com. +** +****************************************************************************/ + +#include "hbicondatacache_p.h" +#include "hbdoublelinkedlist_p.h" +#include "hbmemoryutils_p.h" +#ifdef HB_SGIMAGE_ICON +#include +#include +#include "hbsgimageiconprocessor_p.h" +#endif + +/*! + @hbserver + \class HbIconDataCache + \brief HbIconDataCache provides an implementation for the theme server's icon cache. + It acts as a central repository for storing the various details of all the icons cached in the server. + It provides various methods to insert new items, remove items as well as find existing cached items in the cache. + It also has methods to limit the cache size both on Gpu as well as Cpu shared memory. + + Reference count based caching - On performing an Icon look up in the server, if the icon is not already cached, + the cache item is created and inserted into cache and its reference count is incremented. + If the same icon is requested by another application, the cached instance is returned and only the reference + count is incremented. Similarly, the refrence count is decremented whenever an icon is destroyed. + + LRU policy is used for removal of icons from cache. + The cache maintains two separate doubly link lists to maintain the order of the least recently used icons created + in GPU memory as well as those created in the shared memory. Whenever, the reference count for a cached item becomes 0, + it is not deleted from the cache rather; the cached icon instance is appended to the LRU list. + Consider now that a scenario arrives when the cache has reached its max limit and there are some unused icons + (i.e. icons with reference count = 0) in the LRU list. Suppose at this point there is a new icon caching request. + In such a scenario, the unused icons, starting with those at the beginning of the LRU lists are removed from the cache, + one after the other, till the new icon can be accommodated. + + Description of data members + // A list that maintains an ordered collection of least recently used icons in GPU + // which are not being referred to anymore( i.e icons with reference count = 0) + HbDLinkList gpuLruList; + // A list that maintains an ordered collection of least recently used icons in CPU + // which are not being referred to anymore( i.e icons with reference count = 0) + HbDLinkList cpuLruList; + // Consolidated size of the GPU Cache being occupied by Icons + int currentGpuCacheSize; + // Consolidated size of the CPU Cache being occupied by Icons + int currentCpuCacheSize; + // Consolidated size of all the icons with reference count = 0 in GPU Cache + int gpuLruListSize; + // Consolidated size of all the icons with reference count = 0 in CPU Cache + int cpuLruListSize; + // Maximum GPU Cache Limit size + int maxGpuCacheLimit; + // Maximum CPU Cache Limit size + int maxCpuCacheLimit; + +*/ + + +/*! + \fn HbIconDataCache::HbIconDataCache() + Constructor + */ +HbIconDataCache::HbIconDataCache() + : gpuLruList(&HbIconCacheItem::gpuLink), + cpuLruList(&HbIconCacheItem::cpuLink), + currentGpuCacheSize(0), + currentCpuCacheSize(0), + gpuLruListSize(0), + cpuLruListSize(0), + maxGpuCacheLimit(0), + maxCpuCacheLimit(0), + goodMemory(true) +{ + cache = new QHash(); + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemRefCount = 0; + addedItemMem = 0; + removedItemMem = 0; + enableCaching = true; + cacheHit = 0; + cacheMiss = 0; + vectorLruListCount = 0; + rasterLruListCount = 0; + remRfCount = 0; +#endif +} + +/*! + \fn HbIconDataCache::~HbIconDataCache() + Destructor + */ +HbIconDataCache::~HbIconDataCache() +{ + clear(); + + delete cache; +} + + +/*! + \fn HbIconDataCache::clear() + Clears the complete cache. Also clears the LRU lists. + + */ +void HbIconDataCache::clear() +{ + currentGpuCacheSize = 0; + currentCpuCacheSize = 0; + gpuLruListSize = 0; + cpuLruListSize = 0; + + gpuLruList.removeAll(); + cpuLruList.removeAll(); + + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) + QHash::const_iterator itEnd(cache->constEnd()); + for (QHash < HbIconKey, + HbIconCacheItem* >::const_iterator iter = cache->constBegin(); + iter != itEnd; + ++iter) { + HbIconCacheItem* temp = iter.value(); + if (temp->rasterIconData.type != INVALID_FORMAT) { + switch (temp->rasterIconData.type) { + case PIC : + manager->free(temp->rasterIconData.picData.offset); + break; + case NVG : + manager->free(temp->rasterIconData.nvgData.offset); + break; + case OTHER_SUPPORTED_FORMATS : + manager->free(temp->rasterIconData.pixmapData.offset); + break; + case SGIMAGE: +#ifdef HB_SGIMAGE_ICON + HbSgImageRenderer::removeSgImageFromHash(temp->rasterIconData.sgImageData.id); +#endif + break; + default: + break; + } + } + if (temp->vectorIconData.type != INVALID_FORMAT) { + switch (temp->vectorIconData.type) { + case PIC : + manager->free(temp->vectorIconData.picData.offset); + break; + case NVG : + manager->free(temp->vectorIconData.nvgData.offset); + break; + case OTHER_SUPPORTED_FORMATS : + manager->free(temp->vectorIconData.pixmapData.offset); + break; + default: + break; + } + } + if (temp->blobIconData.type == BLOB) { + manager->free(temp->blobIconData.blobData.offset); + } + delete iter.value(); + } + cache->clear(); + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemRefCount = 0; + addedItemMem = 0; + removedItemMem = 0; + remRfCount = 0; + enableCaching = true; + cacheHit = 0; + cacheMiss = 0; + vectorLruListCount = 0; + rasterLruListCount = 0; +#endif + +} + +/*! + \fn HbIconDataCache::getCacheItem() + Provides a mechanism for finidng whether a cache item is present in the cache. + If found, returns the cache item and increments the reference count else returns NULL. + \a key denotes the unique identifier for the cache item that is to be searched in the cache. + + */ +HbIconCacheItem* HbIconDataCache::getCacheItem(const HbIconKey &key , + bool isMultiIconPiece) +{ + HbIconCacheItem* item = 0; + + if (!cache->contains(key)) { + return 0; + } + // Get the cache item associated with the key + item = (*cache)[(key)]; + +//Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemMem = item->rasterIconDataCost; + cacheHit++; +#endif + + // If the Icon is present in GPU LRU list, then remove it from the list + if (((item->gpuLink.next() != 0) || (item->gpuLink.prev() != 0)) || + ((item == gpuLruList.front()) && (item == gpuLruList.back()))) { + gpuLruList.removeNode(item); + updateGpuLruSize(-item->rasterIconDataCost); + if (gpuLruListSize < 0) { + gpuLruListSize = 0; + } + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemMem = item->rasterIconDataCost; + rasterLruListCount--; + if (rasterLruListCount < 0) { + rasterLruListCount = 0; + } +#endif + } + + // If the Icon does not have GPU shared data and there is enough space to cache + // the icon in GPU cache now, we go ahead and create GPU shared data + if ((item->rasterIconData.type == INVALID_FORMAT) && + (goodMemory && !isMultiIconPiece)) { + if (item->vectorIconData.type == NVG) { + + HbIconCacheItemCreator::createCacheItem(*item, key); + if (item->rasterIconData.type != INVALID_FORMAT) { + currentGpuCacheSize += item->rasterIconDataCost; + } + } + +//Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemMem = item->rasterIconDataCost; +#endif + } + + // If the Icon is present in CPU LRU list, then remove it from the list + if (((item->cpuLink.next() != 0) || (item->cpuLink.prev() != 0)) || + ((item == cpuLruList.front()) && (item == cpuLruList.back()))) { + cpuLruList.removeNode(item); + if (item->rasterIconData.type == OTHER_SUPPORTED_FORMATS) { + updateCpuLruSize(-item->rasterIconDataCost); + } else { + updateCpuLruSize(-item->vectorIconDataCost); + } + + if (cpuLruListSize < 0){ + cpuLruListSize = 0; + } + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemMem = item->vectorIconDataCost; + vectorLruListCount--; + if (vectorLruListCount < 0) { + vectorLruListCount = 0; + } +#endif + } + + // If the Icon does not have CPU data and there is enough space to create + // the icon in CPU cache now, we go ahead and create CPU shared data + if ((item->vectorIconData.type == INVALID_FORMAT) && + (item->rasterIconData.type == SGIMAGE)) { + + if ((item->vectorIconDataCost < (maxCpuCacheLimit - currentCpuCacheSize))) { + HbIconCacheItemCreator::createCacheItem(*item, key); + if (item->vectorIconData.type != INVALID_FORMAT) { + currentCpuCacheSize += item->vectorIconDataCost; + } + } + } + item->refCount ++; + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + addedItemRefCount = item->refCount; + qDebug() << "HbIconDataCache::getCacheItem: " << "Cache hit in Server-Cache for" << key.filename; + qDebug() << "HbIconDataCache::getCacheItem: Server RefCount now = " << item->refCount; +#endif + + return item; +} + +/*! + \fn HbIconDataCache::insert() + Provides a mechanism for inserting items into the cache. + Checks are first done to see whether item can be accomodated in the GPU memory. + If so the Gpu limits are updated. Next it tries to cache the item in the Cpu. + If possible, the Cpu limits are updated. If niether is possible, a failure to insert is returned. + In case of success, the item is inserted into the cache and the reference count for the item is incremented by 1. + \a key denotes the unique identifier for the cache item that is to be inserted into the cache. + \a item the cache item that is to be inserted into the cache. + + */ +bool HbIconDataCache::insert(const HbIconKey &key, HbIconCacheItem* item) +{ + if (!item) + return false; + + // Check if Item can be accomdated in GPU cache + bool gpuCaching = isItemCachableInGpu(item); + // Check if Item can be accomdated in CPU cache + bool cpuCaching = isItemCachableInCpu(item); + + // Item cannot be inserted either into GPU cache memory or CPU cache memory + if ((!gpuCaching) && (!cpuCaching)) { + return false; + } + + // Item can be accomdated in GPU cache + if (gpuCaching) { + // Increment the GPU cache size + if( item->rasterIconDataCost <= maxGpuCacheLimit ) { + currentGpuCacheSize += item->rasterIconDataCost; + } + } + + // Item can be accomdated in CPU cache + if (cpuCaching) { + if (item->rasterIconData.type == OTHER_SUPPORTED_FORMATS) { + if (item->rasterIconDataCost <= (maxCpuCacheLimit - currentCpuCacheSize)) { + currentCpuCacheSize += item->rasterIconDataCost; + } else { + createCpuCacheSpace(item->rasterIconDataCost); + currentCpuCacheSize += item->rasterIconDataCost; + } + } + if (item->vectorIconData.type != INVALID_FORMAT) { + // Increment the CPU cache size + if (item->vectorIconDataCost <= (maxCpuCacheLimit - currentCpuCacheSize)) { + currentCpuCacheSize += item->vectorIconDataCost; + } else { + // New item's icon data cost is more than available free CPU cahe size + // Check if some items, whose ref count is 0, can be removed to make way for new item + createCpuCacheSpace(item->vectorIconDataCost); + currentCpuCacheSize += item->vectorIconDataCost; + } + } + + if (currentCpuCacheSize > maxCpuCacheLimit) { + currentCpuCacheSize = maxCpuCacheLimit; + } + } + QHash::iterator iter = cache->insert(key, const_cast(item)); + if (iter == cache->end()) { + return false; + } + + item->refCount ++; + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + cacheMiss++; + addedItemRefCount = item->refCount; + if (gpuCaching) { + addedItemMem = item->rasterIconDataCost; + } else if (cpuCaching) { + addedItemMem = item->vectorIconDataCost; + } + qDebug() << "HbIconDataCache::insert: " << "Item " << key.filename<<" inserted in Server-Cache"; + qDebug() << "HbIconDataCache::insert: Server RefCount now = " << item->refCount; +#endif + + return true; +} + +/*! + \fn HbIconDataCache::remove() + Remove provides a mechanism for decrementing the reference count of a cached item. + In case the reference count becomes 0, the cache item instance is appended to the corresponding LRU list. + Actual removal of the cache item from the cache only occurs when the cache has reached a max limit and a new request for + insert comes. + \a key denotes the unique identifier for the cache item whose ref count is to be decremented in the cache. + + */ +bool HbIconDataCache::remove(const HbIconKey& key) +{ + if (key.filename.isEmpty() || !cache->contains(key)) { + return false; + } + HbIconCacheItem* item = (*cache)[(key)]; + item->refCount--; + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + remRfCount = item->refCount; +#endif + + if (item->refCount == 0) { + if (item->rasterIconData.type == SGIMAGE) { + gpuLruList.insertBack(item); + updateGpuLruSize(item->rasterIconDataCost); + } + + if (item->rasterIconData.type == OTHER_SUPPORTED_FORMATS) { + cpuLruList.insertBack(item); + updateCpuLruSize(item->rasterIconDataCost); + } + + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + if (! enableCaching) { + currentGpuCacheSize -= item->rasterIconDataCost; + removedItemMem = item->rasterIconDataCost; + removeFromCache(key, item); + rasterLruListCount--; + if (rasterLruListCount < 0) { + rasterLruListCount = 0; + } + + if (currentGpuCacheSize < 0) { + currentGpuCacheSize = 0; + } + } else { +#endif + + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + rasterLruListCount++; + } +#endif + + + if ((item->vectorIconData.type != INVALID_FORMAT) && item->refCount == 0) { + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + if (! enableCaching) { + currentCpuCacheSize -= item->vectorIconDataCost; + removedItemMem = item->vectorIconDataCost; + removeFromCache(key, item); + vectorLruListCount--; + if (vectorLruListCount < 0) { + vectorLruListCount = 0; + } + if (currentCpuCacheSize < 0) { + currentCpuCacheSize = 0; + } + } else { +#endif + + cpuLruList.insertBack(item); + updateCpuLruSize(item->vectorIconDataCost); + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + vectorLruListCount++; + } +#endif + } + } + return true; +} + +/*! + \fn HbIconDataCache::setMaxGpuCacheSize() + Provides an internal mechanism for setting the Gpu cache limit + \a size denotes the cache limit in bytes e.g. size = 0x500000 + + */ +void HbIconDataCache::setMaxGpuCacheSize(int size) +{ + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + if (maxGpuCacheLimit != size) { + if (maxGpuCacheLimit > size) { + // remove the item with refcount = 0 in the cache + // i.e all the item in both LRU lists. + cleanRasterLRUList(); + if (size <= currentGpuCacheSize) { + maxGpuCacheLimit = currentGpuCacheSize; + } else { + maxGpuCacheLimit = size; + } + } else { + maxGpuCacheLimit = size; + } + } +#else + maxGpuCacheLimit = size; +#endif + +} + +/*! + \fn HbIconDataCache::setMaxCpuCacheSize() + Provides an internal mechanism for setting the Cpu cache limit + \a size denotes the cache limit in bytes e.g. size = 0x500000 + */ +void HbIconDataCache::setMaxCpuCacheSize(int size) +{ + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + if (maxCpuCacheLimit != size) { + if (maxCpuCacheLimit > size) { + // remove the item with refcount = 0 in the cache + // i.e all the item in both LRU lists. + cleanVectorLRUList(); + if (size <= currentCpuCacheSize) { + maxGpuCacheLimit = currentCpuCacheSize; + } else { + maxCpuCacheLimit = size; + } + } else { + maxCpuCacheLimit = size; + } + } +#else + maxCpuCacheLimit = size; +#endif +} + +/*! + \fn HbIconDataCache::contains() + Provides a mecahnism for finding whether an item exists in cache. + Is different from the find function in that, this function simply checks whether an item is presentin cache, whereas find + also performs additional operations such as incrementing the reference count. + \a key denotes the unique identifier for the cache item that is to be found into the cache. + + */ +bool HbIconDataCache::contains(const HbIconKey &key)const +{ + return (cache->contains(key)); +} + +/*! + \fn HbIconDataCache::value() + Value provides a mechanism for returning the value of the cache item associated with the key + \a key denotes the unique identifier for the cache item whose value is to be returned + + */ +HbIconCacheItem* HbIconDataCache::value(const HbIconKey &key)const +{ + if (cache->contains(key)) { + return cache->value(key); + } else { + return 0; + } +} + + +/*! + \fn HbIconDataCache::isItemCachableInGpu() + Checks if the new item can be accomdated in the Gpu memory. + \a item is the new item to be cached + BLOB is always cached in cpu so this function always returns false for such items. + */ +bool HbIconDataCache::isItemCachableInGpu(const HbIconCacheItem* item)const +{ + if (maxGpuCacheLimit <= 0 || item->rasterIconDataCost <= 0 || item->blobIconData.type != INVALID_FORMAT || + item->rasterIconData.type != SGIMAGE) { + return false; + } + // Item's GPU Icon's cost is greater than the max GPU Limit + if (item->rasterIconDataCost > maxGpuCacheLimit) + return false; + + return true; +} + +/*! + \fn HbIconDataCache::isItemCachableInCpu() + Checks if the new item can be accomdated in the cpu shared memory. + \a item is the new item to be cached + BLOB is always cached in cpu, never in gpu. + */ +bool HbIconDataCache::isItemCachableInCpu(const HbIconCacheItem* item)const +{ + if (maxCpuCacheLimit <= 0) { + return false; + } + if (item->rasterIconData.type == OTHER_SUPPORTED_FORMATS) { + if (item->rasterIconDataCost <= 0 || item->rasterIconDataCost > maxCpuCacheLimit) { + return false; + } + if (item->rasterIconDataCost <= (maxCpuCacheLimit - currentCpuCacheSize)) { + return true; + } else { + return (item->rasterIconDataCost <= (maxCpuCacheLimit - currentCpuCacheSize) + cpuLruListSize); + } + } + + if (item->vectorIconData.type != INVALID_FORMAT) { + if (item->vectorIconDataCost <= 0 || item->vectorIconDataCost > maxCpuCacheLimit) { + return false; + } + if (item->vectorIconDataCost <= (maxCpuCacheLimit - currentCpuCacheSize)) { + return true; + } else { + return (item->vectorIconDataCost <= (maxCpuCacheLimit - currentCpuCacheSize) + cpuLruListSize); + } + } + return false; +} + +/*! + \fn HbIconDataCache::createGpuCacheSpace() + This method provides a way to remove the unused icons( icons with ref count =0. + It starts removing the icons from the cache, starting with those that are at the front of the Gpu LRU list. + It continues removal of items till there is enough space created to cache the new item in Gpu + \a itemCost - cost of the new item to be cached in the Gpu memory + + */ +void HbIconDataCache::createGpuCacheSpace(int itemCost) +{ + if (!gpuLruList.isEmpty()) { + // Keep removing items from the cache till there is + // enough space to accomdate the new item + int freedMemory = 0; + while (itemCost > (freedMemory)) { + HbIconCacheItem* itemToRemove = gpuLruList.removeFront(); + // Decrement the Size by the cost of the removed icon's data cost + //GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) + //qDebug() << "HbIconDataCache : Calling SgImage Close. Cost = %d "<< itemToRemove->rasterIconDataCost; +#ifdef HB_SGIMAGE_ICON +#ifdef HB_ICON_CACHE_DEBUG + qDebug() << "HbIconDataCache : Calling SgImage Close. Cost = %d "<< itemToRemove->rasterIconDataCost; +#endif + HbSgImageRenderer::removeSgImageFromHash(itemToRemove->rasterIconData.sgImageData.id); +#endif + itemToRemove->rasterIconData.type = INVALID_FORMAT; + itemToRemove->gpuLink.setNext(0); + itemToRemove->gpuLink.setPrev(0); + currentGpuCacheSize -= itemToRemove->rasterIconDataCost; + updateGpuLruSize(-itemToRemove->rasterIconDataCost); + freedMemory += itemToRemove->rasterIconDataCost; + + if (currentGpuCacheSize < 0) { + currentGpuCacheSize = 0; + } + + if (gpuLruListSize < 0) { + gpuLruListSize = 0; + } + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + removedItemMem = itemToRemove->rasterIconDataCost; + rasterLruListCount--; + if (rasterLruListCount < 0) { + rasterLruListCount = 0; + } +#endif + + // This is the case where Icon has no CPU data and + // the GPU cached data has also been deleted to make way for new Icon + // In such a case the Item can be removed from the Hash + + if ((itemToRemove->rasterIconData.type == INVALID_FORMAT) && + (itemToRemove->vectorIconData.type == INVALID_FORMAT)) { + cache->remove(cache->key(itemToRemove)); + delete itemToRemove; + } + } + } +} + +/*! + \fn HbIconDataCache::createCpuCacheSpace() + This method provides a way to remove the unused icons( icons with ref count =0). + It starts removing the icons from the cache, starting with those that are at the front of the CPU LRU list. + It continues removal of items till there is enough space created to cache the new item in Cpu + \a itemCost - cost of the new item to be cached in the Cpu memory + + */ +void HbIconDataCache::createCpuCacheSpace(int itemCost) +{ + if (!cpuLruList.isEmpty()) { + // Keep removing items from the cache till there is + // enough space to accomdate the new item + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) + while (itemCost > (maxCpuCacheLimit - currentCpuCacheSize)) { + HbIconCacheItem* itemToRemove = cpuLruList.removeFront(); + if (itemToRemove->rasterIconData.type == OTHER_SUPPORTED_FORMATS) { + manager->free(itemToRemove->rasterIconData.pixmapData.offset); + itemToRemove->rasterIconData.type = INVALID_FORMAT; + currentCpuCacheSize -= itemToRemove->rasterIconDataCost; + updateCpuLruSize(-itemToRemove->rasterIconDataCost); + } else { + // Decrement the Size by the cost of the removed icon's data cost + if((itemToRemove->vectorIconData.type == PIC)){ + manager->free(itemToRemove->vectorIconData.picData.offset); + } else if (itemToRemove->vectorIconData.type == NVG) { + manager->free(itemToRemove->vectorIconData.nvgData.offset); + } else if (itemToRemove->blobIconData.type == BLOB) { + manager->free(itemToRemove->blobIconData.blobData.offset); + } + + itemToRemove->vectorIconData.type = INVALID_FORMAT; + currentCpuCacheSize -= itemToRemove->vectorIconDataCost; + updateCpuLruSize(-itemToRemove->vectorIconDataCost); + } + + + itemToRemove->cpuLink.setNext(0); + itemToRemove->cpuLink.setPrev(0); + + if (currentCpuCacheSize < 0) { + currentCpuCacheSize = 0; + } + + if (cpuLruListSize < 0) { + cpuLruListSize = 0; + } + + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + removedItemMem = itemToRemove->vectorIconDataCost; + vectorLruListCount--; + if (vectorLruListCount < 0) { + vectorLruListCount = 0; + } +#endif + + // This is the case where Icon has no CPU data and + // the GPU cached data has also been deleted to make way for new Icon + // In such a case the Item can be removed from the Hash + + if ((itemToRemove->vectorIconData.type == INVALID_FORMAT) && + (itemToRemove->rasterIconData.type == INVALID_FORMAT)) { + cache->remove(cache->key(itemToRemove)); + delete itemToRemove; + } + } + } +} + +void HbIconDataCache::updateGpuLruSize(int iconDataCost) +{ + gpuLruListSize += iconDataCost; +} + +void HbIconDataCache::updateCpuLruSize(int iconDataCost) +{ + cpuLruListSize += iconDataCost; +} + +void HbIconDataCache::memoryGood() +{ + goodMemory = true; +} + +void HbIconDataCache::freeGpuRam(int bytes) +{ + goodMemory = false; + if (bytes <= gpuLruListSize) { + createGpuCacheSpace(bytes); + } else { + createGpuCacheSpace(gpuLruListSize); + } +} + +//Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG +void HbIconDataCache::cleanVectorLRUList() +{ + + // remove all the items in cpu LRU list. + while (cpuLruList.front()) { + HbIconCacheItem* itemToRemove = cpuLruList.removeFront(); + + // update the member + currentCpuCacheSize -= itemToRemove->vectorIconDataCost; + cpuLruListSize -= itemToRemove->vectorIconDataCost; + if (currentCpuCacheSize < 0) { + currentCpuCacheSize = 0; + } + + if (cpuLruListSize < 0) { + cpuLruListSize = 0; + } + +#ifdef HB_ICON_CACHE_DEBUG + removedItemMem = itemToRemove->vectorIconDataCost; + vectorLruListCount--; + if (vectorLruListCount < 0) { + vectorLruListCount = 0; + } +#endif + + // remove the shared memory allocatedfor this item. + releaseVectorItem(itemToRemove); + + // release item from cache + removeFromCache(cache->key(itemToRemove), itemToRemove); + } +} + +void HbIconDataCache::releaseVectorItem(HbIconCacheItem* releaseItem) +{ + if (!releaseItem) { + return; + } + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) + // release the specific items data + if (releaseItem->vectorIconData.type == OTHER_SUPPORTED_FORMATS) { + manager->free(releaseItem->vectorIconData.pixmapData.offset); + } else if ((releaseItem->vectorIconData.type == PIC) || + (releaseItem->vectorIconData.type == SVG)) { + manager->free(releaseItem->vectorIconData.picData.offset); + } else if (releaseItem->vectorIconData.type == NVG) { + manager->free(releaseItem->vectorIconData.nvgData.offset); + } else if (releaseItem->blobIconData.type == BLOB) { + manager->free(releaseItem->blobIconData.blobData.offset); + } + releaseItem->vectorIconData.type = INVALID_FORMAT; + releaseItem->cpuLink.setNext(0); + releaseItem->cpuLink.setPrev(0); +} + +void HbIconDataCache::cleanRasterLRUList() +{ + + // remove all the items from the gpu LRU list + while (gpuLruList.front()) { + HbIconCacheItem* itemToRemove = gpuLruList.removeFront(); + + // update the member + currentGpuCacheSize -= itemToRemove->rasterIconDataCost; + gpuLruListSize -= itemToRemove->rasterIconDataCost; + + if (currentGpuCacheSize < 0) { + currentGpuCacheSize = 0; + } + + if (gpuLruListSize < 0) { + gpuLruListSize = 0; + } +#ifdef HB_ICON_CACHE_DEBUG + removedItemMem = itemToRemove->rasterIconDataCost; + rasterLruListCount--; + if (rasterLruListCount < 0) { + rasterLruListCount = 0; + } +#endif + + // release the shared memory (later raster memory)of this item. + releaseRasterItem(itemToRemove); + + // relese from the cache. + removeFromCache(cache->key(itemToRemove), itemToRemove); + } +} + +void HbIconDataCache::releaseRasterItem(HbIconCacheItem* releaseItem) +{ + if (!releaseItem) { + return; + } + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) + // release the removed item data + manager->free(releaseItem->rasterIconData.pixmapData.offset); + releaseItem->rasterIconData.type = INVALID_FORMAT; +} + +void HbIconDataCache::removeFromCache(const HbIconKey &key, const HbIconCacheItem* releaseItem) +{ + if (!releaseItem) { + return; + } + + if ((releaseItem->vectorIconData.type == INVALID_FORMAT) && + (releaseItem->rasterIconData.type == INVALID_FORMAT)) { + cache->remove(key); + delete releaseItem; + } +} + +int HbIconDataCache::count() const +{ + return cache->count(); +} + +int HbIconDataCache::gpuLRUSize() const +{ + return gpuLruListSize; +} + +int HbIconDataCache::freeVectorMemory() +{ + return (maxCpuCacheLimit - currentCpuCacheSize); +} + +int HbIconDataCache::freeRasterMemory() +{ + return (maxGpuCacheLimit - currentGpuCacheSize); +} +int HbIconDataCache::lastAddedRefCount() +{ + return addedItemRefCount; +} +int HbIconDataCache::lastAddedItemMem() +{ + return addedItemMem; +} +int HbIconDataCache::lastRemovedItemMem() +{ + return removedItemMem; +} + +int HbIconDataCache::lastRemovedItemRfCount() +{ + return remRfCount; +} + +bool HbIconDataCache::enableCache(bool cacheIt) +{ + bool success = false; + if (enableCaching != cacheIt) { + enableCaching = cacheIt; + if (!enableCaching) { + cleanVectorLRUList(); + cleanRasterLRUList(); + } + success = true; + } + return success; +} + +int HbIconDataCache::cacheHitCount() +{ + return cacheHit; +} + +int HbIconDataCache::cacheMissCount() +{ + return cacheMiss; +} + +int HbIconDataCache::rasterLruCount() +{ + return gpuLruListSize; +} + +int HbIconDataCache::vectorLruCount() +{ + return cpuLruListSize; +} +#endif