diff -r 7516d6d86cf5 -r ed14f46c0e55 src/hbservers/hbthemeserver/hbthemeserverutils.cpp --- a/src/hbservers/hbthemeserver/hbthemeserverutils.cpp Mon Oct 04 17:49:30 2010 +0300 +++ b/src/hbservers/hbthemeserver/hbthemeserverutils.cpp Mon Oct 18 18:23:13 2010 +0300 @@ -25,11 +25,14 @@ #include "hbthemeserverutils_p.h" +#include +#include +#include +#include #include #include #include -#include -#include +#include #include "hbmemoryutils_p.h" #include "hbcssparser_p.h" @@ -37,7 +40,6 @@ #include "hbeffectxmlparser_p.h" #include "hbdeviceprofiledatabase_p.h" #include "hbthemeperf_p.h" -#include "hbcache_p.h" #include "hbiconsource_p.h" #include "hbwidgetloader_p.h" #include "hbwidgetloaderactions_p.h" @@ -53,9 +55,18 @@ typedef QHash ServerHashForLayoutDefs; Q_GLOBAL_STATIC(ServerHashForLayoutDefs, layoutDefsCache) +// Offset for the cache of the missed CSS files for classes starting 'hb' +static int missedHbCssFilesOffset = -1; +static const QString HB_CLASSNAME_PREFIX("hb"); + static const int ICON_SOURCES_MAX_SIZE = 8; static QList iconSources; // cache of recently used icon sources + +const int PIXEL_DEPTH = 4; +const int TILE_SIZE_IN_PIXELS = 32 * 32; +const int SGIMAGE_PIXEL_OVERHEAD = 200; + HbIconSource *HbThemeServerUtils::getIconSource(const QString &filename) { foreach(HbIconSource *source, iconSources) { @@ -107,9 +118,10 @@ */ int HbThemeServerUtils::getSharedStylesheet(const QString &fileName, HbLayeredStyleLoader::LayerPriority priority, + bool &fileExists, bool *inSharedCache) { - int cssOffset = -1; + qptrdiff cssOffset = -1; HbSharedCache *sharedCache = 0; if (priority == HbLayeredStyleLoader::Priority_Core) { sharedCache = HbSharedCache::instance(); @@ -121,16 +133,12 @@ *inSharedCache = false; } -#ifdef THEME_SERVER_TRACES - qDebug() << "In " << Q_FUNC_INFO; -#endif // THEME_SERVER_TRACES if (cssOffset < 0) { - if (QFile::exists(fileName)) { - HbCss::Parser parser; - if (!parseCssFile(parser, fileName, cssOffset)) { - if (parser.errorCode == HbCss::Parser::OutOfMemoryError) { - return OUT_OF_MEMORY_ERROR; - } + THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "Stylesheet: " << fileName << " not found in shared cache."; + HbCss::Parser parser; + if (!parseCssFile(parser, fileName, cssOffset, fileExists)) { + if (parser.errorCode == HbCss::Parser::OutOfMemoryError) { + return OUT_OF_MEMORY_ERROR; } } if (sharedCache) { //sharedCache valid only when priority is Priority_Core @@ -140,13 +148,41 @@ return cssOffset; } +/* + * Returns the offset of the missed CSS files for widgets starting with 'hb' + */ +int HbThemeServerUtils::getMissedHbCssFilesOffset() +{ + if (missedHbCssFilesOffset < 0) { + initMissedHbCssFilesList(); + } + return missedHbCssFilesOffset; +} + +void HbThemeServerUtils::initMissedHbCssFilesList() +{ + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); + int offset = -1; + try { + offset = manager->alloc(sizeof(HbVector)); + HbVector *list = new((char*)manager->base() + offset) + HbVector(HbMemoryManager::SharedMemory); + } catch (std::bad_alloc &) { + if (offset >= 0) { + manager->free(offset); + offset = -1; + } + } + missedHbCssFilesOffset = offset; +} + /** * HbThemeServerUtils::parseCssFile() * * Returns false in case Css file has some error or there is not enough memory */ bool HbThemeServerUtils::parseCssFile(HbCss::Parser &parser, const QString &fileName, - int &cssOffset) + qptrdiff &cssOffset, bool &fileExists) { bool retVal = false; // 1. Create a styleSheet in shared memory @@ -168,7 +204,21 @@ return retVal; } // 2. Parse the required file into styleSheet. - parser.init(fileName, true); + fileExists = parser.init(fileName, true); + if (!fileExists) { + if (QFileInfo(fileName).fileName().startsWith(HB_CLASSNAME_PREFIX)) { + HbVector *list = HbMemoryUtils::getAddress >( + HbMemoryManager::SharedMemory, getMissedHbCssFilesOffset()); + if (list) { + list->append(qHash(fileName)); + } + } + if (cssOffset != -1) { + manager->free(cssOffset); + cssOffset = -1; + } + return retVal; + } retVal = parser.parse(styleSheet); if (!retVal) { @@ -189,9 +239,9 @@ */ int HbThemeServerUtils::getSharedLayoutDefinition(const QString &fileName, const QString &layout, - const QString §ion) + const QString §ion, bool &fileExists) { - int layoutDefOffset = -1; + qptrdiff layoutDefOffset = -1; QStringRef nameKey(&fileName); if (nameKey.at(0) == ':') { //use only filename as a key. @@ -218,13 +268,12 @@ HbWidgetLoader loader; QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - qWarning("Unable to open file"); + fileExists = file.open(QFile::ReadOnly | QFile::Text); + if (!fileExists) { + THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "Unable to open the file: " << fileName; return -1; } -#ifdef THEME_SERVER_TRACES - qDebug() << "Trying to load: " << fileName << "::" << layout << "::" << section; -#endif // THEME_SERVER_TRACES + THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "Trying to load: " << fileName << "::" << layout << "::" << section; HbWidgetLoader::LayoutDefinition *layoutDef(0); GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); @@ -307,24 +356,15 @@ */ int HbThemeServerUtils::getSharedEffect(const QString &fileName) { -#ifdef THEME_SERVER_TRACES - qDebug() << "In " << Q_FUNC_INFO << fileName; -#endif // THEME_SERVER_TRACES + THEME_GENERIC_DEBUG() << Q_FUNC_INFO << "called with fileName: " << fileName; - int effOffset = -1; + qptrdiff effOffset = -1; if (effCache()->contains(fileName)) { effOffset = effCache()->value(fileName); - -#ifdef THEME_SERVER_TRACES - qDebug() << "Got effect in cache: " << fileName << "offset=" << effOffset; -#endif //THEME_SERVER_TRACES - + THEME_GENERIC_DEBUG() << "in cache: " << fileName << "offset=" << effOffset; } else { - -#ifdef THEME_SERVER_TRACES - qDebug() << "Not in cache, parsing: " << fileName; -#endif //THEME_SERVER_TRACES - + THEME_GENERIC_DEBUG() << "Not in cache, parsing: " << fileName; + // 1. Create an effect in shared memory GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); HbEffectFxmlData *data = 0; @@ -339,85 +379,69 @@ manager->free(effOffset); effOffset = -1; } + THEME_GENERIC_DEBUG() << "Exception when allocating shared memory."; return effOffset; } // 2. Parse the file. HbEffectXmlParser parser; + QBuffer fxmlBuffer; QFile f(fileName); bool fail = false; - if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { + + if (f.open(QIODevice::ReadOnly)) { try { - parser.read(&f, data); - f.close(); + QByteArray arr(f.readAll()); + fxmlBuffer.setBuffer(&arr); + if (fxmlBuffer.open(QIODevice::ReadOnly | QIODevice::Text)) { + parser.read(&fxmlBuffer, data); + } else { + THEME_GENERIC_DEBUG() << "Cannot open fxmlBuffer from file:" << fileName; + fail = true; + } // 3. Mark an entry for this styleSheet into the table - effCache()->insert(fileName, effOffset); + if (!fail) { + effCache()->insert(fileName, effOffset); + } } catch (std::exception &) { - f.close(); fail = true; } } else { -#ifdef THEME_SERVER_TRACES - qWarning() << "Cannot open" << fileName; -#endif // THEME_SERVER_TRACES + THEME_GENERIC_DEBUG() << "Cannot open:" << fileName; fail = true; } if (fail) { data->~HbEffectFxmlData(); manager->free(effOffset); + THEME_GENERIC_DEBUG() << "Failed to parse effect."; return -1; } + // These will be open, if we got here + f.close(); + fxmlBuffer.close(); + // add the filename and css offset to the secondary cache. // no need to check if this item is already present in the // cache as the parsing of the file happens only once // in the server side. HbSharedCache::instance()->add(HbSharedCache::Effect, fileName, effOffset); } - -#ifdef THEME_SERVER_TRACES - qDebug() << "returning offset: " << effOffset; -#endif // THEME_SERVER_TRACES - + + THEME_GENERIC_DEBUG() << "returning offset: " << effOffset; return effOffset; } -/** - * cleanupUnusedCss function removes css-resources (stylesheets), whose reference count - * is zero, it also releases the shared memory occupied by those resources. - * \param cache server css-cache - * - */ -void HbThemeServerUtils::cleanupUnusedCss(HbCache *cache) -{ - QList list = cache->lruList(); - while (!list.isEmpty()) { - HbCacheItem* itemToRemove = list.takeFirst(); - if (itemToRemove->offset != -1) { - HbCss::StyleSheet *styleSheet = - HbMemoryUtils::getAddress(HbMemoryManager::SharedMemory, - itemToRemove->offset); - HbMemoryUtils::release(styleSheet); - itemToRemove->offset = -1; - } - //Since we are cleaning up css-resources whose ref-count is zero, these entries will be - // removed from actual cache. - delete cache->cacheHandle().take(itemToRemove->fileName); - } -} - void HbThemeServerUtils::createThemeIndex(const QString &themePath, const HbThemeType &themetype) { - #ifdef THEME_INDEX_TRACES - qDebug() << "ThemeIndex: createThemeIndex" << themePath.toUtf8(); - #endif + THEME_INDEX_DEBUG() << "ThemeIndex: createThemeIndex" << themePath.toUtf8(); QDir themeBasePath(themePath); // Path is like "C:/resource/hb/themes/icons/sfwhitetheme" QString themeName = themeBasePath.dirName(); QString filename(themeBasePath.absolutePath()); - int cutindex = filename.lastIndexOf("/",filename.lastIndexOf("/")-1)+1; + int cutindex = filename.lastIndexOf('/',filename.lastIndexOf('/')-1)+1; filename = filename.left(cutindex); themeBasePath.setPath(filename); filename.append(themeName); @@ -434,55 +458,35 @@ bool indexOK = false; if (indexFile.open(QIODevice::ReadOnly)) { - indexOK = true; - GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); - HbSharedChunkHeader *chunkHeader = (HbSharedChunkHeader*) manager->base(); - + HbSharedChunkHeader *chunkHeader = (HbSharedChunkHeader*) manager->base(); qint64 byteSize = indexFile.size(); - - #ifdef THEME_INDEX_TRACES - qDebug() << "ThemeIndex: " << themeName.toUtf8() << " index file size:" << byteSize; - #endif + THEME_INDEX_DEBUG() << "ThemeIndex: " << themeName.toUtf8() << " index file size:" << byteSize; int offset = manager->alloc(byteSize); if (offset >= 0) { - #ifdef THEME_INDEX_TRACES - qDebug() << "ThemeIndex: memory allocated for theme: " << themeName.toUtf8(); - #endif + THEME_INDEX_DEBUG() << "ThemeIndex: memory allocated for theme: " << themeName.toUtf8(); // Read the theme index in the shared chunk char *address = HbMemoryUtils::getAddress(HbMemoryManager::SharedMemory, offset); indexFile.read(address, byteSize); indexFile.close(); - - #ifdef THEME_INDEX_TRACES - qDebug() << "ThemeIndex: Reading themeindex for theme" << themeName.toUtf8() << "... Done!"; - #endif + THEME_INDEX_DEBUG() << "ThemeIndex: Reading themeindex for theme" << themeName.toUtf8() << "... Done!"; // Verify theme index contents if it is not located in ROM, // so that it does not have over-indexing offsets which might // crash all the clients trying to read from it. -#ifdef Q_OS_SYMBIAN // ROM check only for Symbian - verify always in other platforms. if (themePath[0] != 'z' && themePath[0] != 'Z') { -#endif - #ifdef THEME_INDEX_TRACES - qDebug() << "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8(); - #endif - + THEME_INDEX_DEBUG() << "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8(); HbThemeIndex index(address); indexOK = index.validateItems(byteSize); + THEME_INDEX_DEBUG() << "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8() << " done! Result: " << indexOK; + } - #ifdef THEME_INDEX_TRACES - qDebug() << "ThemeIndex: Validating themeindex for theme" << themeName.toUtf8() << " done! Result: " << indexOK; - #endif -#ifdef Q_OS_SYMBIAN - } -#endif if (indexOK) { // Allocate theme path string from shared memory QByteArray themePathArray = themeBasePath.absolutePath().toLatin1(); @@ -555,4 +559,131 @@ } } +int HbThemeServerUtils::computeCpuCost(const HbIconKey & key, HbIconFormatType iconType, + bool isConsolidatedIcon) +{ + int cpuItemCost = 0; + if (isConsolidatedIcon) { + QSize size = key.size.toSize(); + cpuItemCost = size.width() * size.height() * PIXEL_DEPTH; + return cpuItemCost; + } + HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename); + if (source) { + if (iconType == BLOB) { + QByteArray *sourceByteArray = source->byteArray(); + if (sourceByteArray) { + cpuItemCost = sourceByteArray->length(); + } + } else if (iconType == NVG) { + QByteArray *sourceByteArray = source->byteArray(); + if (sourceByteArray) { + QSizeF renderSize = source->defaultSize(); + if (!key.size.isNull()) { + renderSize.scale(key.size,key.aspectRatioMode); + } + QSize size = renderSize.toSize(); + cpuItemCost = size.width() * size.height() * PIXEL_DEPTH; + } + } else if (iconType == SVG) { + QSvgRenderer *svgRenderer = source->svgRenderer(); + if (svgRenderer && svgRenderer->isValid()) { + QSizeF renderSize = QSizeF(svgRenderer->defaultSize()); + if (!key.size.isNull()) { + renderSize.scale(key.size, key.aspectRatioMode); + } + QSize size = renderSize.toSize(); + cpuItemCost = size.width() * size.height() * PIXEL_DEPTH; + source->releaseSvgRenderer(); + + } + } else { + QPixmap pm = QPixmap::fromImage(*source->image()); + QSizeF renderSize = pm.size(); + if (!key.size.isNull() ) { + renderSize.scale(key.size, key.aspectRatioMode); + } + QSize size = renderSize.toSize(); + cpuItemCost = size.width() * size.height() * PIXEL_DEPTH; + + } + + } + return cpuItemCost; +} + +int HbThemeServerUtils::computeGpuCost(const HbIconKey & key, HbIconFormatType iconType, + bool isConsolidatedIcon) +{ + int gpuItemCost = 0; + if (isConsolidatedIcon) { + QSize size = key.size.toSize(); + int xTiles = ceil(size.width() / 32.0); + int yTiles = ceil(size.height() / 32.0); + int sizeInPixels = xTiles * yTiles * TILE_SIZE_IN_PIXELS; + int sizeInBytes = sizeInPixels * PIXEL_DEPTH; + gpuItemCost = sizeInBytes + SGIMAGE_PIXEL_OVERHEAD ; + return gpuItemCost; + } + HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename); + if (source) { + if (iconType == NVG) { + QByteArray *sourceByteArray = source->byteArray(); + if (sourceByteArray) { + QSizeF renderSize = source->defaultSize(); + if (!key.size.isNull()) { + renderSize.scale(key.size,key.aspectRatioMode); + } + QSize size = renderSize.toSize(); + int xTiles = ceil(size.width() / 32.0); + int yTiles = ceil(size.height() / 32.0); + int sizeInPixels = xTiles * yTiles * TILE_SIZE_IN_PIXELS; + int sizeInBytes = sizeInPixels * PIXEL_DEPTH; + gpuItemCost = sizeInBytes + SGIMAGE_PIXEL_OVERHEAD ; + } + } + } + return gpuItemCost; + +} + +int HbThemeServerUtils::computeFrameItemCpuCost(const HbIconKey & key, HbIconFormatType iconType, + HbRenderingMode rm) +{ + int cpuItemCost = 0; + HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename); + if (source) { + if (iconType == SVG) { + QSvgRenderer *svgRenderer = source->svgRenderer(); + if (svgRenderer && svgRenderer->isValid()) { + QSizeF renderSize = QSizeF(svgRenderer->defaultSize()); + if (!key.size.isNull()) { + renderSize.scale(key.size, key.aspectRatioMode); + } + QSize size = renderSize.toSize(); + cpuItemCost = size.width() * size.height() * PIXEL_DEPTH; + source->releaseSvgRenderer(); + + } + } else if (iconType == NVG) { + QByteArray *sourceByteArray = source->byteArray(); + if (sourceByteArray) { + if (rm == EHWRendering ) { + cpuItemCost = sourceByteArray->length(); + } else { + QSizeF renderSize = source->defaultSize(); + if (!key.size.isNull()) { + renderSize.scale(key.size,key.aspectRatioMode); + } + QSize size = renderSize.toSize(); + cpuItemCost = size.width() * size.height() * PIXEL_DEPTH; + } + } + } + } + return cpuItemCost; + +} + +