graphicsdeviceinterface/directgdiadaptation/hwsrc/vgimagecache.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "vgimagecache.h"
       
    17 #include "directgdiadapter.h"
       
    18 
       
    19 /**
       
    20 Given a TDisplayMode, returns the closest TDisplayMode that is pixel-for-pixel-compatible
       
    21 with an OpenVG format, such that the given TDisplayMode may be converted into the result
       
    22 without loss of colour information.
       
    23 
       
    24 @param 	aDisplayMode Pixel format to find a match for.
       
    25 
       
    26 @return Closest TDisplayMode for which there is a OpenVG-compatible match.
       
    27 */
       
    28 static TDisplayMode ClosestVgCompatibleDisplayMode (TDisplayMode aDisplayMode)
       
    29 	{
       
    30 	switch (aDisplayMode)
       
    31 		{
       
    32 		case EGray2:
       
    33 		case EGray4:
       
    34 		case EGray16:
       
    35 			return EGray256;
       
    36 
       
    37 		case EColor16:
       
    38 		case EColor256:
       
    39 		case EColor4K:
       
    40 			return EColor64K;
       
    41 		
       
    42 		case EColor16M:
       
    43 			return EColor16MU;
       
    44 			
       
    45 		default:
       
    46 			return aDisplayMode;
       
    47 		}
       
    48 	}
       
    49 
       
    50 
       
    51 /**
       
    52 Image Cache Item constructor.
       
    53 */
       
    54 CVgImageCache::CVgImageCacheItem::CVgImageCacheItem()
       
    55 	{
       
    56 	
       
    57 	}
       
    58 
       
    59 /**
       
    60 Image Cache Item destructor.
       
    61 Destroys the VGImage owned by the cache item.
       
    62 */
       
    63 CVgImageCache::CVgImageCacheItem::~CVgImageCacheItem()
       
    64 	{
       
    65 	vgDestroyImage(iImage);
       
    66 	}
       
    67 
       
    68 
       
    69 
       
    70 /**
       
    71 Forms a 32-bit hash value from a 64-bit integer.
       
    72 
       
    73 @param aKey The 64-bit key to be hashed.
       
    74 @return 32-bit hash value.
       
    75 */
       
    76 TUint32 CVgImageCache::Hash(const TInt64& aKey)
       
    77 	{
       
    78 	TPckgC<TInt64> bytes(aKey);
       
    79 	return DefaultHash::Des8(bytes);
       
    80 	}
       
    81 
       
    82 /**
       
    83 Image Cache constructor.
       
    84 Initialises the hashmap and double-linked queue
       
    85 */
       
    86 CVgImageCache::CVgImageCache(TInt aMaxCacheSize)
       
    87 	:iCacheItemMap(THashFunction32<TInt64>(CVgImageCache::Hash), TIdentityRelation<TInt64>()),
       
    88 	iVgImageCache(_FOFF(CVgImageCacheItem, iLink)),
       
    89 	iMaxCacheSizeInBytes(aMaxCacheSize)
       
    90 	{
       
    91 	}
       
    92 
       
    93 /**
       
    94 Image Cache destructor.
       
    95 Iterates through all the items in the cache and deletes them.
       
    96  */
       
    97 CVgImageCache::~CVgImageCache()
       
    98 	{
       
    99 	// cycle through all the items and destroy the VGImages.
       
   100 	TDblQueIter<CVgImageCacheItem> iter(iVgImageCache);
       
   101 	CVgImageCacheItem* item;
       
   102 	while((item=iter++)!=NULL)
       
   103 		{
       
   104 		DeleteItem(item);
       
   105 		}
       
   106 	iCacheItemMap.Close();
       
   107 	}
       
   108 
       
   109 /**
       
   110 Deletes a cache item.
       
   111 This removes the supplied item from the queue and the hashmap,
       
   112 destroys the VGImage in that item, and deletes the item itself.
       
   113 @param aItem The image cache item to be deleted.
       
   114  */
       
   115 void CVgImageCache::DeleteItem(CVgImageCacheItem* aItem)
       
   116 	{
       
   117 	aItem->iLink.Deque();
       
   118 	iCacheSizeInBytes -= aItem->iImageSizeInBytes;
       
   119 	iCacheItemMap.Remove(aItem->iSerialNumber);
       
   120 	delete aItem;
       
   121 	}
       
   122 
       
   123 /**
       
   124 Adds a VGImage to the cache using the associated CFbsBitmap as a reference.
       
   125 
       
   126 A new image cache item is created which stores the VGImage, the size of the image in pixels,
       
   127 the serial number of the CFbsBitmap (which acts as a unique identifier) and the touch count
       
   128 of the CFbsBitmap.  The touch count determines the number of times the underlying data of
       
   129 the CFbsBitmap has changed.
       
   130 
       
   131 The least-recently used items will be removed from the cache to create space for the new item, if needed.
       
   132 
       
   133 @param aBitmap	The bitmap from which the VGImage was created.
       
   134 @param aImage	The VGImage to store in the cache.
       
   135 @param aOrigin	The origin used to create a tiled VGImage.
       
   136 
       
   137 @return ETrue if the VGImage was successfully added to the cache, EFalse if not.
       
   138  */
       
   139 TBool CVgImageCache::AddImage(const CFbsBitmap& aBitmap, VGImage& aImage, const TPoint& aOrigin)
       
   140 	{
       
   141 	// Calculate approximate size in bytes of image
       
   142 	TDisplayMode vgCompatibleDisplayMode = ClosestVgCompatibleDisplayMode(aBitmap.DisplayMode());
       
   143 	TSize imageSize = aBitmap.SizeInPixels();
       
   144 	TInt dataStride = CFbsBitmap::ScanLineLength(imageSize.iWidth, vgCompatibleDisplayMode);
       
   145 	TInt imageSizeInBytes = imageSize.iHeight * dataStride;
       
   146 	// if size of image is too large to fit in cache 
       
   147 	if(imageSizeInBytes > iMaxCacheSizeInBytes)
       
   148 		{
       
   149 		return EFalse;
       
   150 		}
       
   151 	
       
   152 	CVgImageCacheItem* newItem = new CVgImageCacheItem;
       
   153 	if (newItem == NULL)
       
   154 		{
       
   155 		return EFalse;
       
   156 		}
       
   157 
       
   158 	// check there is enough room in the cache
       
   159 	// i.e. less than user-specified max memory allowed for cache
       
   160 	// if not enough space, remove items from end of cache until enough space is available.
       
   161 	while(iMaxCacheSizeInBytes < iCacheSizeInBytes + imageSizeInBytes)
       
   162 		{
       
   163 		DeleteItem(iVgImageCache.Last());
       
   164 		}
       
   165 	newItem->iSerialNumber = aBitmap.SerialNumber();
       
   166 	newItem->iImage = aImage;
       
   167 	newItem->iTouchCount = aBitmap.TouchCount();
       
   168 	newItem->iOrigin = aOrigin;
       
   169 	newItem->iImageSizeInBytes = imageSizeInBytes;
       
   170 	TInt err = iCacheItemMap.Insert(newItem->iSerialNumber, newItem);
       
   171 	if (err != KErrNone)
       
   172 		{
       
   173 		delete newItem;
       
   174 		return EFalse;
       
   175 		}
       
   176 	iVgImageCache.AddFirst(*newItem);
       
   177 	iCacheSizeInBytes += newItem->iImageSizeInBytes;
       
   178 	return ETrue;
       
   179 	}
       
   180 
       
   181 /**
       
   182 Retrieves the VGImage from the cache that was created from the supplied CFbsBitmap.
       
   183 The cache is first searched to find the item containing the VGImage that was created from the CFbsBitmap.
       
   184 If no matching item is found, no VGImage is returned.
       
   185 If the matching item is found, the touch count is checked to determine whether the
       
   186 CFbsBitmap has been updated since the stored VGImage was created from it.  If it has, the matching item 
       
   187 and VGImage is deleted from the cache and no VGImage is returned.
       
   188 If the matching item is found and the CFbsitmap has not been updated sionce the VGImage was created,
       
   189 the associated VGImage is returned.
       
   190 
       
   191 @param aBitmap	The bitmap used to reference the item containing the VGImage.
       
   192 @param aOrigin  The origin of the VGImage, relative to the top left corner of the source image.
       
   193 
       
   194 @return	VG_INVALID_HANDLE if no VGImage exists for the supplied CFbsBitmap or if the stored VGImage is out of date.
       
   195 		Otherwise the VGImage associated with the CFbsBitmap is returned.
       
   196  */
       
   197 VGImage CVgImageCache::GetVgImageFromBitmap(const CFbsBitmap& aBitmap, const TPoint& aOrigin)
       
   198 	{
       
   199 	// search through cache to find the item with a matching bitmap ID
       
   200 	CVgImageCacheItem** itemPtr = iCacheItemMap.Find(aBitmap.SerialNumber());
       
   201 	++iNumMatchTries;
       
   202 	if(itemPtr == NULL)
       
   203 		{
       
   204 		// searched all the way through cache and there is no matching image
       
   205 		++iNumMatchMisses;
       
   206 		return VG_INVALID_HANDLE;
       
   207 		}
       
   208 	CVgImageCacheItem* item = *itemPtr;
       
   209 	// Check whether the VGImage held by the item is up-to-date
       
   210 	// - check touch counts are equal.
       
   211 	// - check origins used for creating VGImage are equal.
       
   212 	if (aBitmap.TouchCount() != item->iTouchCount || aOrigin != item->iOrigin)
       
   213 		{
       
   214 		// VGImage in item needs updating, so remove and delete the entry
       
   215 		// and return NULL to indicate that a new entry needs to be created.
       
   216 		DeleteItem(item);
       
   217 		return VG_INVALID_HANDLE;
       
   218 		}
       
   219 	// VGImage is up-to date.
       
   220 	// If item is not already at front of list, move it there
       
   221 	if(!iVgImageCache.IsFirst(item))
       
   222 		{
       
   223 		item->iLink.Deque();
       
   224 		iVgImageCache.AddFirst(*item);
       
   225 		}
       
   226 	return item->iImage;
       
   227 	}
       
   228 
       
   229 // Test APIs
       
   230 
       
   231 /**
       
   232 Determines whether an item exists for a specified bitmap's serial number.
       
   233 
       
   234 @param aSerialNumber	The unique identifier of a CFbsBitmap.
       
   235 
       
   236 @return ETrue if a matching item is found using the serial number.  EFalse if not.
       
   237  */
       
   238 TBool CVgImageCache::IsInCache(TInt64 aSerialNumber)
       
   239 	{
       
   240 	return (iCacheItemMap.Find(aSerialNumber) != NULL);
       
   241 	}
       
   242 
       
   243 /**
       
   244 The touch count stored in the item associated with the supplied serial number.
       
   245 
       
   246 @param aSerialNumber	The unique identifier of a CFbsBitmap.
       
   247 
       
   248 @return	The touch count stored in the item associated with the supplied serial number.
       
   249 		KErrNotFound if no matching item is found using the serial number.
       
   250  */
       
   251 TInt CVgImageCache::TouchCount(TInt64 aSerialNumber)
       
   252 	{
       
   253 	CVgImageCacheItem** itemPtr = iCacheItemMap.Find(aSerialNumber);
       
   254 	if(itemPtr == NULL)
       
   255 		{
       
   256 		// searched all the way through cache and there is no matching image
       
   257 		return KErrNotFound;
       
   258 		}
       
   259 	return (*itemPtr)->iTouchCount;
       
   260 	}
       
   261 
       
   262 /**
       
   263 The number of entries in the cache.
       
   264 @return The number of entries in the cache.
       
   265  */
       
   266 TInt CVgImageCache::NumEntries() const
       
   267 	{
       
   268 	return iCacheItemMap.Count();
       
   269 	}
       
   270 
       
   271 /**
       
   272 Returns a list of the serial numbers of all the cache items, with the most-recently used item at ordinal 0
       
   273 and the least-recently used item and the end of the list.
       
   274 
       
   275 @param aSerialNumberList A reference to a list in which to return the serial number list.
       
   276 @param aListSize The number of entries allocated for the list.
       
   277  */
       
   278 void CVgImageCache::GetOrderedCacheEntries(TInt64& aSerialNumberList, TInt aListSize)
       
   279 	{
       
   280 	GRAPHICS_ASSERT_ALWAYS(aSerialNumberList, EDirectGdiPanicInvalidPointArray)
       
   281 	TDblQueIter<CVgImageCacheItem> iter(iVgImageCache);
       
   282 
       
   283 	TInt n = iCacheItemMap.Count();
       
   284 	// If n is greater than number of entries in list, restrict to number of entries.
       
   285 	if (n > aListSize) n = aListSize;
       
   286 	for (TInt ii = 0; ii < n; ++ii)
       
   287 		{
       
   288 		CVgImageCacheItem* item = iter++;
       
   289 		(&aSerialNumberList)[ii] = item->iSerialNumber;
       
   290 		}
       
   291 	
       
   292 	// If n is less than number of entries in list, pad out entries with 0
       
   293 	// (i.e. invlaid serial numbers)
       
   294 	while (n < aListSize)
       
   295 		{
       
   296 		(&aSerialNumberList)[n++] = 0;
       
   297 		}
       
   298 	}
       
   299 
       
   300 /**
       
   301 The total size of the cache in bytes.
       
   302 @return The total size of the cache in bytes.
       
   303  */
       
   304 TInt CVgImageCache::CacheSizeInBytes() const
       
   305 	{
       
   306 	return iCacheSizeInBytes;
       
   307 	}
       
   308 
       
   309 /**
       
   310 The maximum size of the cache in bytes.
       
   311 @return The maximum size of the cache in bytes.
       
   312  */
       
   313 TInt CVgImageCache::MaxCacheSize() const
       
   314 	{
       
   315 	return iMaxCacheSizeInBytes;
       
   316 	}
       
   317 
       
   318 /**
       
   319 Resets the cache. Iterates through all the items in the cache and deletes them.
       
   320  */
       
   321 void CVgImageCache::ResetCache()
       
   322 	{
       
   323 	// cycle through all the items and destroy the VGImages.
       
   324 	TDblQueIter<CVgImageCacheItem> iter(iVgImageCache);
       
   325 	CVgImageCacheItem* item;
       
   326 	while((item=iter++)!=NULL)
       
   327 		{
       
   328 		DeleteItem(item);
       
   329 		}
       
   330 	}
       
   331 
       
   332 /**
       
   333 Sets the maximum size in bytes of the cache. Checks the current size of the
       
   334 cache and sets the maximum cache size if the current cache size is smaller 
       
   335 or equal to aCacheSize.
       
   336 @param aMaxCacheSize The maximum size in bytes to allow for the cache.
       
   337 @return KErrNone if the maximum cache size has been changed successfully,
       
   338 KErrArgument if aMaxCacheSize is smaller than the current cache size.
       
   339  */
       
   340 TInt CVgImageCache::SetMaxCacheSize(TInt aMaxCacheSize)
       
   341 	{
       
   342 	if (iCacheSizeInBytes <= aMaxCacheSize) 
       
   343 		{
       
   344 		iMaxCacheSizeInBytes = aMaxCacheSize;
       
   345 		return KErrNone;
       
   346 		}
       
   347 	
       
   348 	return KErrArgument;
       
   349 	}