uigraphics/AknIcon/srvsrc/AknIconSrvCache.cpp
changeset 0 05e9090e2422
child 55 33ddb261ab37
equal deleted inserted replaced
-1:000000000000 0:05e9090e2422
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Dynamic bitmap caching, SVG DOM tree precaching.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <e32std.h>
       
    22 #include <fbs.h>
       
    23 #include <barsread.h>
       
    24 #include <barsc.h>
       
    25 // Skin server client
       
    26 #include <AknsSrvClient.h>
       
    27 #include <AknIconSrv.rsg>
       
    28 #include <mifconvdefs.h>
       
    29 #include <mifconvdefs.h>
       
    30 
       
    31 #include "AknIconSrvCache.h"
       
    32 #include "AknIconSrv.h"
       
    33 #include "AknIconSrvIconItem.h"
       
    34 #include "AknIconSrvPanic.h"
       
    35 #include "AknIconSrvScheduler.h"
       
    36 #include "AknIconTraces.h"
       
    37 
       
    38 #ifdef PRECACHE2
       
    39 #include "AknIconSrvPrecacher.h"
       
    40 #endif
       
    41 
       
    42 
       
    43 // CONSTANTS
       
    44 
       
    45 // Contains cache configuration, non localized resource file.
       
    46 
       
    47 _LIT( KAknIconResourceFile, "z:\\resource\\akniconsrv.rsc" );
       
    48 #ifdef PRECACHE2
       
    49 _LIT( KPrecacheThreadName2, "AknIconPrecache2" );
       
    50 #endif
       
    51 
       
    52 // ================= MEMBER FUNCTIONS ==========================================
       
    53 
       
    54 CAknIconSrvCache::CAknIconSrvCache( CAknIconServer& aServer ) : 
       
    55  iDynamicallyCached( 8 ), iServer( aServer )
       
    56     {
       
    57     }
       
    58 
       
    59 CAknIconSrvCache::~CAknIconSrvCache()
       
    60     {
       
    61     iDynamicallyCached.Close();
       
    62     iPrecache.Close();
       
    63     
       
    64 
       
    65     }
       
    66 
       
    67 CAknIconSrvCache* CAknIconSrvCache::NewL( CAknIconServer& aServer )
       
    68     {
       
    69     CAknIconSrvCache* self = new( ELeave ) CAknIconSrvCache( aServer );
       
    70     CleanupStack::PushL( self );
       
    71     self->ConstructL();
       
    72     CleanupStack::Pop();
       
    73 
       
    74     return self;
       
    75     }
       
    76 
       
    77 TDisplayMode MapConfigToDspMode(TInt aValue)
       
    78     {
       
    79     if ( aValue == 0 ) // value documented in the resource file
       
    80         {
       
    81         return EColor64K;
       
    82         }
       
    83     else if ( aValue == 2 ) // value documented in the resource file
       
    84         {
       
    85         return EColor16MU;
       
    86         }
       
    87     // Default to EColor16M, which is fastest to render alpha-blended.
       
    88     else
       
    89         {
       
    90         return EColor16M;
       
    91         }
       
    92     }
       
    93 
       
    94 TDisplayMode MapConfigToMaskMode(TInt aValue)
       
    95     {
       
    96     if ( aValue == 0 ) // value documented in the resource file
       
    97         {
       
    98         return EGray2;
       
    99         }
       
   100     // Default to EGray256
       
   101     else
       
   102         {
       
   103         return EGray256;
       
   104         }
       
   105     }
       
   106 
       
   107 TInt ReadConfigValue32L(const RResourceFile& aFile, TInt aResourceId)
       
   108     {
       
   109     TInt var;
       
   110     TPckg<TInt> pack( var );
       
   111     aFile.ReadL( pack, aResourceId );
       
   112     return var;
       
   113     }
       
   114 
       
   115 #ifdef PRECACHE2
       
   116 void DoPrecache2L( TAny* aParameters )
       
   117     {
       
   118     CAknIconSrvPrecacher* cacher = NULL;
       
   119     cacher = CAknIconSrvPrecacher::NewL(*(static_cast<CAknIconServer*>( aParameters )) );
       
   120     cacher->Start();
       
   121     delete cacher;
       
   122     }
       
   123 
       
   124 GLDEF_C TInt PrecacheThreadFunction2( TAny* aParameters )
       
   125     {
       
   126     
       
   127     CTrapCleanup* cleanup = CTrapCleanup::New();
       
   128     CActiveScheduler* scheduler = new CActiveScheduler;
       
   129     if(!scheduler)
       
   130         {
       
   131         delete cleanup;
       
   132         return KErrBadHandle;
       
   133         }
       
   134     CActiveScheduler::Install( scheduler );
       
   135     TInt err = KErrNone;
       
   136     TRAP(err,DoPrecache2L(aParameters));
       
   137     delete scheduler;
       
   138     delete cleanup;
       
   139     
       
   140 
       
   141     
       
   142     return err;
       
   143     }
       
   144 #endif // PRECACHE2
       
   145 void CAknIconSrvCache::ConstructL()
       
   146     {
       
   147 #ifdef PRECACHE2
       
   148     User::LeaveIfError( iServer.iPreCacheThread.Create(
       
   149         KPrecacheThreadName2,
       
   150         PrecacheThreadFunction2,
       
   151         0x2000, // stack size
       
   152         NULL, // uses caller thread's heap
       
   153         (TAny*)&iServer ) );
       
   154     iServer.iPreCacheThread.SetPriority(KPreCache2Priority);
       
   155     iServer.iPreCacheThread.Resume();
       
   156 #endif // PRECACHE2
       
   157     // Read resource file configuration.
       
   158     RResourceFile file;
       
   159     // Also prepare to the case that the resource file does not exist.
       
   160     TRAPD( err, file.OpenL( iServer.FsSession(), KAknIconResourceFile ) );
       
   161 
       
   162   
       
   163     
       
   164 
       
   165     if ( err == KErrNone )
       
   166         {
       
   167         CleanupClosePushL( file );
       
   168 
       
   169         // Read bitmap compression config and set server variable.
       
   170         TUint8 var1;
       
   171         TPckg<TUint8> pack1( var1 );
       
   172         file.ReadL( pack1, R_COMPRESS_BITMAPS );
       
   173         iServer.iCompression = var1;
       
   174 
       
   175         // read bitmap depth configs and set the server values
       
   176         TInt value = ReadConfigValue32L(file, R_PREFERRED_ICON_DEPTH);
       
   177         iServer.iIconMode = MapConfigToDspMode(value);
       
   178 
       
   179         value = ReadConfigValue32L(file, R_PREFERRED_ICON_MASK_DEPTH);
       
   180         iServer.iIconMaskMode = MapConfigToMaskMode(value);
       
   181         
       
   182         value = ReadConfigValue32L(file, R_PREFERRED_PHOTO_DEPTH);
       
   183         iServer.iPhotoMode = MapConfigToDspMode(value);
       
   184 
       
   185         value = ReadConfigValue32L(file, R_PREFERRED_VIDEO_DEPTH);
       
   186         iServer.iVideoMode = MapConfigToDspMode(value);
       
   187 
       
   188         value = ReadConfigValue32L(file, R_PREFERRED_OFFSCREEN_DEPTH);
       
   189         iServer.iOffscreenMode = MapConfigToDspMode(value);
       
   190 
       
   191         value = ReadConfigValue32L(file, R_PREFERRED_OFFSCREEN_MASK_DEPTH);
       
   192         iServer.iOffscreenMaskMode = MapConfigToMaskMode(value);
       
   193 
       
   194 
       
   195 
       
   196 
       
   197         TPckg<TInt> pack3( iConfiguredMaxDynamicCacheSize );
       
   198         file.ReadL( pack3, R_MAX_DYNAMIC_CACHE_SIZE );
       
   199         EnableCache( ETrue );
       
   200 
       
   201 
       
   202 
       
   203         CleanupStack::PopAndDestroy( 1); // file
       
   204         }
       
   205     
       
   206 
       
   207         // If no thread launched, complete request immediately.
       
   208         TRequestStatus* status = &( iServer.ThreadLaunchStatus() );
       
   209         User::RequestComplete( status, KErrNone );
       
   210        
       
   211 
       
   212         
       
   213     }
       
   214 
       
   215 
       
   216 
       
   217 
       
   218 
       
   219 // -----------------------------------------------------------------------------
       
   220 // CAknIconSrvCache::CacheUnusedIcon
       
   221 // 
       
   222 // Caches an icon (in bitmap form) that has just become unused.
       
   223 // -----------------------------------------------------------------------------
       
   224 //
       
   225 TBool CAknIconSrvCache::CacheUnusedIcon( CAknIconSrvIconItem& aItem )
       
   226     {
       
   227     // If cache size is set to zero, return EFalse always.
       
   228 #ifdef __AKNICON_TRACES
       
   229     RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: iMaxDynamicCacheSize=%d"), this, iMaxDynamicCacheSize);
       
   230 #endif        
       
   231     if ( !iMaxDynamicCacheSize )
       
   232         {           
       
   233         return EFalse;
       
   234         }
       
   235 
       
   236     TBool ret = EFalse;
       
   237     TInt lCacheSize  = iDynamicCacheSize + iPrecacheSize ;
       
   238     TInt iconDataSize = IconDataSize( aItem );
       
   239     if ( iconDataSize <= iMaxDynamicCacheSize )
       
   240         { 
       
   241         // If reached max size of the dynamic cache UpdateDynamicCacheSize.
       
   242         
       
   243         if (lCacheSize + iconDataSize > iMaxDynamicCacheSize)
       
   244             {
       
   245             UpdateDynamicCacheSize();
       
   246             }
       
   247            
       
   248         // If reached max size of the dynamic cache, 
       
   249         // remove older cached items.
       
   250         while ( iDynamicallyCached.Count() > 0 && 
       
   251                 lCacheSize + iconDataSize > iMaxDynamicCacheSize )
       
   252             {
       
   253             CAknIconSrvIconItem* oldest = iDynamicallyCached[0];
       
   254 
       
   255             iDynamicCacheSize -= IconDataSize( *oldest );
       
   256             iDynamicallyCached.Remove( 0 );
       
   257             iServer.RemoveCachedItem( *oldest );
       
   258             
       
   259             if (!iDynamicallyCached.Count())
       
   260                 {
       
   261 #ifdef __AKNICON_TRACES
       
   262     RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: reset iDynamicCacheSize=%d to 0"), this, iDynamicCacheSize);
       
   263 #endif                
       
   264                 iDynamicCacheSize = 0;
       
   265                 }
       
   266             lCacheSize = iDynamicCacheSize + iPrecacheSize ;
       
   267             }
       
   268         // If dynamic cache is empty  
       
   269         // but precache size is greater than maxcachesize
       
   270         // and Precache has some items
       
   271         // and the new item to be added is a precache item
       
   272         // delete the older precache items
       
   273         if (iDynamicallyCached.Count() == 0)
       
   274             {
       
   275             while ( iPrecacheSize + iconDataSize > iMaxDynamicCacheSize 
       
   276              && iPrecache.Count() > 0
       
   277              && aItem.iPrecacheItem)
       
   278                 {
       
   279                 CAknIconSrvIconItem* oldest = iPrecache[0];
       
   280     
       
   281                 iPrecacheSize -= IconDataSize( *oldest );
       
   282                 iPrecache.Remove( 0 );
       
   283                 iServer.RemoveCachedItem( *oldest );
       
   284                 
       
   285                 if (!iPrecache.Count())
       
   286                     {
       
   287 #ifdef __AKNICON_TRACES
       
   288     RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: reset iDynamicCacheSize=%d to 0"), this, iPrecacheSize);
       
   289 #endif                
       
   290                     iPrecacheSize = 0;
       
   291                     }
       
   292                
       
   293                 }
       
   294             }
       
   295         
       
   296         // this check is needed for one case only
       
   297         // if the cache is filled with precache items, dynamic cache is empty
       
   298         // and a non precache item wants to be put in cache 
       
   299         // then dont put it
       
   300         //Insert into dynamicCache or Precache
       
   301         if(lCacheSize + iconDataSize <= iMaxDynamicCacheSize )
       
   302             {
       
   303             TInt lError;
       
   304             if(aItem.iPrecacheItem)
       
   305                 {
       
   306                 lError = iPrecache.Append(&aItem);
       
   307                 }
       
   308             else
       
   309                 {
       
   310                 lError = iDynamicallyCached.Append(&aItem);
       
   311                 }
       
   312                 
       
   313             // If no error encountered in insertion 
       
   314             // set icon as cached
       
   315             if(lError == KErrNone)
       
   316                 {
       
   317                 aItem.SetCached();
       
   318                 if(aItem.iPrecacheItem)
       
   319                     {
       
   320                     iPrecacheSize += iconDataSize;
       
   321                     }
       
   322                 else
       
   323                     {
       
   324                     iDynamicCacheSize += iconDataSize;
       
   325                     }
       
   326                 ret = ETrue;
       
   327                 }
       
   328             }            
       
   329         }
       
   330 
       
   331     // If return ETrue, the server keeps the icon loaded even though the user
       
   332     // count went to zero.
       
   333 #ifdef __AKNICON_TRACES
       
   334     RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: ret=%d"), this, ret);
       
   335 #endif       
       
   336     return ret;
       
   337     }
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // CAknIconSrvCache::UpdateDynamicCacheSize
       
   341 // 
       
   342 // Updates iDynamicCacheSize because its value could be deteriorated over time
       
   343 // due to background bitmap compression.
       
   344 // -----------------------------------------------------------------------------
       
   345 //    
       
   346 void CAknIconSrvCache::UpdateDynamicCacheSize()
       
   347     {
       
   348 #ifdef __AKNICON_TRACES
       
   349     RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::UpdateDynamicCacheSize: old iDynamicCacheSize=%d, iServer.iCompression=%d"), this, iDynamicCacheSize, iServer.iCompression);
       
   350 #endif 
       
   351     // Recalculate iDynamicCacheSize only if bitmap compression is enabled
       
   352     if (iServer.iCompression)
       
   353         {
       
   354         iDynamicCacheSize = 0;
       
   355         for(TInt i = 0; i < iDynamicallyCached.Count(); i++)
       
   356             {
       
   357             iDynamicCacheSize += IconDataSize(*iDynamicallyCached[i]);
       
   358             }    
       
   359         }
       
   360 #ifdef __AKNICON_TRACES
       
   361     RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::UpdateDynamicCacheSize: new iDynamicCacheSize=%d"), this, iDynamicCacheSize);
       
   362 #endif 
       
   363         
       
   364     }
       
   365 // -----------------------------------------------------------------------------
       
   366 // CAknIconSrvCache::RemoveIfCached
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 void CAknIconSrvCache::RemoveIfCached( CAknIconSrvIconItem& aItem )
       
   370     {
       
   371     if ( aItem.IsCached() )
       
   372         {
       
   373         // search for item in iDynamicallyCached & iPrecache
       
   374         TInt lDynamicIndex = iDynamicallyCached.Find( &aItem );
       
   375         TInt lPrecacheIndex = iPrecache.Find(&aItem);
       
   376         
       
   377         __ASSERT_DEBUG( lDynamicIndex >= 0 || lPrecacheIndex >= 0, 
       
   378             User::Panic( KAknIconSrvPanicCategory, ESrvPanicCacheCorrupt ) );
       
   379 
       
   380         if(lDynamicIndex >= 0)
       
   381             {
       
   382             iDynamicallyCached.Remove( lDynamicIndex );
       
   383             iDynamicCacheSize -= IconDataSize( aItem );
       
   384             }
       
   385         else if(lPrecacheIndex >= 0)
       
   386             {
       
   387             iPrecache.Remove(lPrecacheIndex);
       
   388             iPrecacheSize -= IconDataSize(aItem);
       
   389             }
       
   390         
       
   391         aItem.ClearCached();
       
   392         }
       
   393     }
       
   394 
       
   395 // -----------------------------------------------------------------------------
       
   396 // CAknIconSrvCache::DynamicToPrecache
       
   397 // -----------------------------------------------------------------------------
       
   398 //
       
   399 void CAknIconSrvCache::DynamicToPrecache( CAknIconSrvIconItem& aItem )
       
   400     {
       
   401     if ( aItem.IsCached() )
       
   402         {
       
   403         // search for item in iDynamicallyCached 
       
   404         TInt lDynamicIndex = iDynamicallyCached.Find( &aItem );
       
   405         if(lDynamicIndex >= 0)
       
   406             {
       
   407             CAknIconSrvIconItem* moveItem = iDynamicallyCached[lDynamicIndex];
       
   408             
       
   409             if (iPrecache.Append(moveItem) == KErrNone)
       
   410                 {
       
   411                 iPrecacheSize += IconDataSize(aItem);
       
   412             
       
   413                 iDynamicallyCached.Remove( lDynamicIndex );
       
   414                 iDynamicCacheSize -= IconDataSize( aItem );
       
   415                 }
       
   416             }
       
   417         }
       
   418        
       
   419     }
       
   420 
       
   421 
       
   422 
       
   423 // -----------------------------------------------------------------------------
       
   424 // CAknIconSrvCache::ResetDynamicCache
       
   425 // -----------------------------------------------------------------------------
       
   426 //
       
   427 void CAknIconSrvCache::ResetDynamicCache()
       
   428     {
       
   429 #ifdef _DEBUG
       
   430 
       
   431     EnableCache( EFalse );
       
   432 
       
   433 #endif // _DEBUG
       
   434     }
       
   435 
       
   436 // -----------------------------------------------------------------------------
       
   437 // CAknIconSrvCache::IconDataSize
       
   438 // -----------------------------------------------------------------------------
       
   439 //
       
   440 TInt CAknIconSrvCache::IconDataSize( CAknIconSrvIconItem& aItem )
       
   441     {
       
   442     TInt byteSize = aItem.iBitmap->Header().iBitmapSize;
       
   443 
       
   444     if ( aItem.iMask )
       
   445         {
       
   446         byteSize += aItem.iMask->Header().iBitmapSize;
       
   447         }
       
   448 
       
   449     return byteSize;
       
   450     }
       
   451 
       
   452 
       
   453 
       
   454 
       
   455 // -----------------------------------------------------------------------------
       
   456 // CAknIconSrvCache::EnableCache
       
   457 // -----------------------------------------------------------------------------
       
   458 //
       
   459 void CAknIconSrvCache::EnableCache( TBool aEnable )
       
   460 	{
       
   461 	if ( aEnable )
       
   462 		{
       
   463 		// enable the cache by setting the configured max cache size.
       
   464         iMaxDynamicCacheSize = iConfiguredMaxDynamicCacheSize;
       
   465 		}
       
   466 	else
       
   467 		{
       
   468 		// disable the cache by removing all dynamically cached
       
   469 		// icons and setting the max cache size to zero, which will
       
   470 		// prevent further icons from being added.
       
   471 	    while ( iDynamicallyCached.Count() )
       
   472 	        {
       
   473 	        CAknIconSrvIconItem* item = iDynamicallyCached[0];
       
   474 	        iDynamicallyCached.Remove( 0 );
       
   475 	        iServer.RemoveCachedItem( *item );
       
   476 	        }
       
   477 
       
   478 	    iDynamicCacheSize = 0;
       
   479 	    
       
   480 	    while(iPrecache.Count())
       
   481 	        {
       
   482 	        CAknIconSrvIconItem* item = iPrecache[0];
       
   483 	        iPrecache.Remove( 0 );
       
   484 	        iServer.RemoveCachedItem( *item );
       
   485 	        
       
   486 	        }
       
   487 	    iPrecacheSize = 0;
       
   488 	    
       
   489 	    iMaxDynamicCacheSize = 0;
       
   490 	    
       
   491 	    
       
   492 		}
       
   493 	}
       
   494 
       
   495 //  End of File