diff -r 000000000000 -r 05e9090e2422 uigraphics/AknIcon/srvsrc/AknIconSrvCache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uigraphics/AknIcon/srvsrc/AknIconSrvCache.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,495 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Dynamic bitmap caching, SVG DOM tree precaching. +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +// Skin server client +#include +#include +#include +#include + +#include "AknIconSrvCache.h" +#include "AknIconSrv.h" +#include "AknIconSrvIconItem.h" +#include "AknIconSrvPanic.h" +#include "AknIconSrvScheduler.h" +#include "AknIconTraces.h" + +#ifdef PRECACHE2 +#include "AknIconSrvPrecacher.h" +#endif + + +// CONSTANTS + +// Contains cache configuration, non localized resource file. + +_LIT( KAknIconResourceFile, "z:\\resource\\akniconsrv.rsc" ); +#ifdef PRECACHE2 +_LIT( KPrecacheThreadName2, "AknIconPrecache2" ); +#endif + +// ================= MEMBER FUNCTIONS ========================================== + +CAknIconSrvCache::CAknIconSrvCache( CAknIconServer& aServer ) : + iDynamicallyCached( 8 ), iServer( aServer ) + { + } + +CAknIconSrvCache::~CAknIconSrvCache() + { + iDynamicallyCached.Close(); + iPrecache.Close(); + + + } + +CAknIconSrvCache* CAknIconSrvCache::NewL( CAknIconServer& aServer ) + { + CAknIconSrvCache* self = new( ELeave ) CAknIconSrvCache( aServer ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + + return self; + } + +TDisplayMode MapConfigToDspMode(TInt aValue) + { + if ( aValue == 0 ) // value documented in the resource file + { + return EColor64K; + } + else if ( aValue == 2 ) // value documented in the resource file + { + return EColor16MU; + } + // Default to EColor16M, which is fastest to render alpha-blended. + else + { + return EColor16M; + } + } + +TDisplayMode MapConfigToMaskMode(TInt aValue) + { + if ( aValue == 0 ) // value documented in the resource file + { + return EGray2; + } + // Default to EGray256 + else + { + return EGray256; + } + } + +TInt ReadConfigValue32L(const RResourceFile& aFile, TInt aResourceId) + { + TInt var; + TPckg pack( var ); + aFile.ReadL( pack, aResourceId ); + return var; + } + +#ifdef PRECACHE2 +void DoPrecache2L( TAny* aParameters ) + { + CAknIconSrvPrecacher* cacher = NULL; + cacher = CAknIconSrvPrecacher::NewL(*(static_cast( aParameters )) ); + cacher->Start(); + delete cacher; + } + +GLDEF_C TInt PrecacheThreadFunction2( TAny* aParameters ) + { + + CTrapCleanup* cleanup = CTrapCleanup::New(); + CActiveScheduler* scheduler = new CActiveScheduler; + if(!scheduler) + { + delete cleanup; + return KErrBadHandle; + } + CActiveScheduler::Install( scheduler ); + TInt err = KErrNone; + TRAP(err,DoPrecache2L(aParameters)); + delete scheduler; + delete cleanup; + + + + return err; + } +#endif // PRECACHE2 +void CAknIconSrvCache::ConstructL() + { +#ifdef PRECACHE2 + User::LeaveIfError( iServer.iPreCacheThread.Create( + KPrecacheThreadName2, + PrecacheThreadFunction2, + 0x2000, // stack size + NULL, // uses caller thread's heap + (TAny*)&iServer ) ); + iServer.iPreCacheThread.SetPriority(KPreCache2Priority); + iServer.iPreCacheThread.Resume(); +#endif // PRECACHE2 + // Read resource file configuration. + RResourceFile file; + // Also prepare to the case that the resource file does not exist. + TRAPD( err, file.OpenL( iServer.FsSession(), KAknIconResourceFile ) ); + + + + + if ( err == KErrNone ) + { + CleanupClosePushL( file ); + + // Read bitmap compression config and set server variable. + TUint8 var1; + TPckg pack1( var1 ); + file.ReadL( pack1, R_COMPRESS_BITMAPS ); + iServer.iCompression = var1; + + // read bitmap depth configs and set the server values + TInt value = ReadConfigValue32L(file, R_PREFERRED_ICON_DEPTH); + iServer.iIconMode = MapConfigToDspMode(value); + + value = ReadConfigValue32L(file, R_PREFERRED_ICON_MASK_DEPTH); + iServer.iIconMaskMode = MapConfigToMaskMode(value); + + value = ReadConfigValue32L(file, R_PREFERRED_PHOTO_DEPTH); + iServer.iPhotoMode = MapConfigToDspMode(value); + + value = ReadConfigValue32L(file, R_PREFERRED_VIDEO_DEPTH); + iServer.iVideoMode = MapConfigToDspMode(value); + + value = ReadConfigValue32L(file, R_PREFERRED_OFFSCREEN_DEPTH); + iServer.iOffscreenMode = MapConfigToDspMode(value); + + value = ReadConfigValue32L(file, R_PREFERRED_OFFSCREEN_MASK_DEPTH); + iServer.iOffscreenMaskMode = MapConfigToMaskMode(value); + + + + + TPckg pack3( iConfiguredMaxDynamicCacheSize ); + file.ReadL( pack3, R_MAX_DYNAMIC_CACHE_SIZE ); + EnableCache( ETrue ); + + + + CleanupStack::PopAndDestroy( 1); // file + } + + + // If no thread launched, complete request immediately. + TRequestStatus* status = &( iServer.ThreadLaunchStatus() ); + User::RequestComplete( status, KErrNone ); + + + + } + + + + + +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::CacheUnusedIcon +// +// Caches an icon (in bitmap form) that has just become unused. +// ----------------------------------------------------------------------------- +// +TBool CAknIconSrvCache::CacheUnusedIcon( CAknIconSrvIconItem& aItem ) + { + // If cache size is set to zero, return EFalse always. +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: iMaxDynamicCacheSize=%d"), this, iMaxDynamicCacheSize); +#endif + if ( !iMaxDynamicCacheSize ) + { + return EFalse; + } + + TBool ret = EFalse; + TInt lCacheSize = iDynamicCacheSize + iPrecacheSize ; + TInt iconDataSize = IconDataSize( aItem ); + if ( iconDataSize <= iMaxDynamicCacheSize ) + { + // If reached max size of the dynamic cache UpdateDynamicCacheSize. + + if (lCacheSize + iconDataSize > iMaxDynamicCacheSize) + { + UpdateDynamicCacheSize(); + } + + // If reached max size of the dynamic cache, + // remove older cached items. + while ( iDynamicallyCached.Count() > 0 && + lCacheSize + iconDataSize > iMaxDynamicCacheSize ) + { + CAknIconSrvIconItem* oldest = iDynamicallyCached[0]; + + iDynamicCacheSize -= IconDataSize( *oldest ); + iDynamicallyCached.Remove( 0 ); + iServer.RemoveCachedItem( *oldest ); + + if (!iDynamicallyCached.Count()) + { +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: reset iDynamicCacheSize=%d to 0"), this, iDynamicCacheSize); +#endif + iDynamicCacheSize = 0; + } + lCacheSize = iDynamicCacheSize + iPrecacheSize ; + } + // If dynamic cache is empty + // but precache size is greater than maxcachesize + // and Precache has some items + // and the new item to be added is a precache item + // delete the older precache items + if (iDynamicallyCached.Count() == 0) + { + while ( iPrecacheSize + iconDataSize > iMaxDynamicCacheSize + && iPrecache.Count() > 0 + && aItem.iPrecacheItem) + { + CAknIconSrvIconItem* oldest = iPrecache[0]; + + iPrecacheSize -= IconDataSize( *oldest ); + iPrecache.Remove( 0 ); + iServer.RemoveCachedItem( *oldest ); + + if (!iPrecache.Count()) + { +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: reset iDynamicCacheSize=%d to 0"), this, iPrecacheSize); +#endif + iPrecacheSize = 0; + } + + } + } + + // this check is needed for one case only + // if the cache is filled with precache items, dynamic cache is empty + // and a non precache item wants to be put in cache + // then dont put it + //Insert into dynamicCache or Precache + if(lCacheSize + iconDataSize <= iMaxDynamicCacheSize ) + { + TInt lError; + if(aItem.iPrecacheItem) + { + lError = iPrecache.Append(&aItem); + } + else + { + lError = iDynamicallyCached.Append(&aItem); + } + + // If no error encountered in insertion + // set icon as cached + if(lError == KErrNone) + { + aItem.SetCached(); + if(aItem.iPrecacheItem) + { + iPrecacheSize += iconDataSize; + } + else + { + iDynamicCacheSize += iconDataSize; + } + ret = ETrue; + } + } + } + + // If return ETrue, the server keeps the icon loaded even though the user + // count went to zero. +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: ret=%d"), this, ret); +#endif + return ret; + } + +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::UpdateDynamicCacheSize +// +// Updates iDynamicCacheSize because its value could be deteriorated over time +// due to background bitmap compression. +// ----------------------------------------------------------------------------- +// +void CAknIconSrvCache::UpdateDynamicCacheSize() + { +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::UpdateDynamicCacheSize: old iDynamicCacheSize=%d, iServer.iCompression=%d"), this, iDynamicCacheSize, iServer.iCompression); +#endif + // Recalculate iDynamicCacheSize only if bitmap compression is enabled + if (iServer.iCompression) + { + iDynamicCacheSize = 0; + for(TInt i = 0; i < iDynamicallyCached.Count(); i++) + { + iDynamicCacheSize += IconDataSize(*iDynamicallyCached[i]); + } + } +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::UpdateDynamicCacheSize: new iDynamicCacheSize=%d"), this, iDynamicCacheSize); +#endif + + } +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::RemoveIfCached +// ----------------------------------------------------------------------------- +// +void CAknIconSrvCache::RemoveIfCached( CAknIconSrvIconItem& aItem ) + { + if ( aItem.IsCached() ) + { + // search for item in iDynamicallyCached & iPrecache + TInt lDynamicIndex = iDynamicallyCached.Find( &aItem ); + TInt lPrecacheIndex = iPrecache.Find(&aItem); + + __ASSERT_DEBUG( lDynamicIndex >= 0 || lPrecacheIndex >= 0, + User::Panic( KAknIconSrvPanicCategory, ESrvPanicCacheCorrupt ) ); + + if(lDynamicIndex >= 0) + { + iDynamicallyCached.Remove( lDynamicIndex ); + iDynamicCacheSize -= IconDataSize( aItem ); + } + else if(lPrecacheIndex >= 0) + { + iPrecache.Remove(lPrecacheIndex); + iPrecacheSize -= IconDataSize(aItem); + } + + aItem.ClearCached(); + } + } + +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::DynamicToPrecache +// ----------------------------------------------------------------------------- +// +void CAknIconSrvCache::DynamicToPrecache( CAknIconSrvIconItem& aItem ) + { + if ( aItem.IsCached() ) + { + // search for item in iDynamicallyCached + TInt lDynamicIndex = iDynamicallyCached.Find( &aItem ); + if(lDynamicIndex >= 0) + { + CAknIconSrvIconItem* moveItem = iDynamicallyCached[lDynamicIndex]; + + if (iPrecache.Append(moveItem) == KErrNone) + { + iPrecacheSize += IconDataSize(aItem); + + iDynamicallyCached.Remove( lDynamicIndex ); + iDynamicCacheSize -= IconDataSize( aItem ); + } + } + } + + } + + + +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::ResetDynamicCache +// ----------------------------------------------------------------------------- +// +void CAknIconSrvCache::ResetDynamicCache() + { +#ifdef _DEBUG + + EnableCache( EFalse ); + +#endif // _DEBUG + } + +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::IconDataSize +// ----------------------------------------------------------------------------- +// +TInt CAknIconSrvCache::IconDataSize( CAknIconSrvIconItem& aItem ) + { + TInt byteSize = aItem.iBitmap->Header().iBitmapSize; + + if ( aItem.iMask ) + { + byteSize += aItem.iMask->Header().iBitmapSize; + } + + return byteSize; + } + + + + +// ----------------------------------------------------------------------------- +// CAknIconSrvCache::EnableCache +// ----------------------------------------------------------------------------- +// +void CAknIconSrvCache::EnableCache( TBool aEnable ) + { + if ( aEnable ) + { + // enable the cache by setting the configured max cache size. + iMaxDynamicCacheSize = iConfiguredMaxDynamicCacheSize; + } + else + { + // disable the cache by removing all dynamically cached + // icons and setting the max cache size to zero, which will + // prevent further icons from being added. + while ( iDynamicallyCached.Count() ) + { + CAknIconSrvIconItem* item = iDynamicallyCached[0]; + iDynamicallyCached.Remove( 0 ); + iServer.RemoveCachedItem( *item ); + } + + iDynamicCacheSize = 0; + + while(iPrecache.Count()) + { + CAknIconSrvIconItem* item = iPrecache[0]; + iPrecache.Remove( 0 ); + iServer.RemoveCachedItem( *item ); + + } + iPrecacheSize = 0; + + iMaxDynamicCacheSize = 0; + + + } + } + +// End of File