os/graphics/graphicsdeviceinterface/directgdiadaptation/hwsrc/vgimagecache.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}