graphicsdeviceinterface/directgdiadaptation/hwsrc/vgimagecache.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdiadaptation/hwsrc/vgimagecache.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,349 @@
+// Copyright (c) 2007-2009 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:
+//
+
+#include "vgimagecache.h"
+#include "directgdiadapter.h"
+
+/**
+Given a TDisplayMode, returns the closest TDisplayMode that is pixel-for-pixel-compatible
+with an OpenVG format, such that the given TDisplayMode may be converted into the result
+without loss of colour information.
+
+@param 	aDisplayMode Pixel format to find a match for.
+
+@return Closest TDisplayMode for which there is a OpenVG-compatible match.
+*/
+static TDisplayMode ClosestVgCompatibleDisplayMode (TDisplayMode aDisplayMode)
+	{
+	switch (aDisplayMode)
+		{
+		case EGray2:
+		case EGray4:
+		case EGray16:
+			return EGray256;
+
+		case EColor16:
+		case EColor256:
+		case EColor4K:
+			return EColor64K;
+		
+		case EColor16M:
+			return EColor16MU;
+			
+		default:
+			return aDisplayMode;
+		}
+	}
+
+
+/**
+Image Cache Item constructor.
+*/
+CVgImageCache::CVgImageCacheItem::CVgImageCacheItem()
+	{
+	
+	}
+
+/**
+Image Cache Item destructor.
+Destroys the VGImage owned by the cache item.
+*/
+CVgImageCache::CVgImageCacheItem::~CVgImageCacheItem()
+	{
+	vgDestroyImage(iImage);
+	}
+
+
+
+/**
+Forms a 32-bit hash value from a 64-bit integer.
+
+@param aKey The 64-bit key to be hashed.
+@return 32-bit hash value.
+*/
+TUint32 CVgImageCache::Hash(const TInt64& aKey)
+	{
+	TPckgC<TInt64> bytes(aKey);
+	return DefaultHash::Des8(bytes);
+	}
+
+/**
+Image Cache constructor.
+Initialises the hashmap and double-linked queue
+*/
+CVgImageCache::CVgImageCache(TInt aMaxCacheSize)
+	:iCacheItemMap(THashFunction32<TInt64>(CVgImageCache::Hash), TIdentityRelation<TInt64>()),
+	iVgImageCache(_FOFF(CVgImageCacheItem, iLink)),
+	iMaxCacheSizeInBytes(aMaxCacheSize)
+	{
+	}
+
+/**
+Image Cache destructor.
+Iterates through all the items in the cache and deletes them.
+ */
+CVgImageCache::~CVgImageCache()
+	{
+	// cycle through all the items and destroy the VGImages.
+	TDblQueIter<CVgImageCacheItem> iter(iVgImageCache);
+	CVgImageCacheItem* item;
+	while((item=iter++)!=NULL)
+		{
+		DeleteItem(item);
+		}
+	iCacheItemMap.Close();
+	}
+
+/**
+Deletes a cache item.
+This removes the supplied item from the queue and the hashmap,
+destroys the VGImage in that item, and deletes the item itself.
+@param aItem The image cache item to be deleted.
+ */
+void CVgImageCache::DeleteItem(CVgImageCacheItem* aItem)
+	{
+	aItem->iLink.Deque();
+	iCacheSizeInBytes -= aItem->iImageSizeInBytes;
+	iCacheItemMap.Remove(aItem->iSerialNumber);
+	delete aItem;
+	}
+
+/**
+Adds a VGImage to the cache using the associated CFbsBitmap as a reference.
+
+A new image cache item is created which stores the VGImage, the size of the image in pixels,
+the serial number of the CFbsBitmap (which acts as a unique identifier) and the touch count
+of the CFbsBitmap.  The touch count determines the number of times the underlying data of
+the CFbsBitmap has changed.
+
+The least-recently used items will be removed from the cache to create space for the new item, if needed.
+
+@param aBitmap	The bitmap from which the VGImage was created.
+@param aImage	The VGImage to store in the cache.
+@param aOrigin	The origin used to create a tiled VGImage.
+
+@return ETrue if the VGImage was successfully added to the cache, EFalse if not.
+ */
+TBool CVgImageCache::AddImage(const CFbsBitmap& aBitmap, VGImage& aImage, const TPoint& aOrigin)
+	{
+	// Calculate approximate size in bytes of image
+	TDisplayMode vgCompatibleDisplayMode = ClosestVgCompatibleDisplayMode(aBitmap.DisplayMode());
+	TSize imageSize = aBitmap.SizeInPixels();
+	TInt dataStride = CFbsBitmap::ScanLineLength(imageSize.iWidth, vgCompatibleDisplayMode);
+	TInt imageSizeInBytes = imageSize.iHeight * dataStride;
+	// if size of image is too large to fit in cache 
+	if(imageSizeInBytes > iMaxCacheSizeInBytes)
+		{
+		return EFalse;
+		}
+	
+	CVgImageCacheItem* newItem = new CVgImageCacheItem;
+	if (newItem == NULL)
+		{
+		return EFalse;
+		}
+
+	// check there is enough room in the cache
+	// i.e. less than user-specified max memory allowed for cache
+	// if not enough space, remove items from end of cache until enough space is available.
+	while(iMaxCacheSizeInBytes < iCacheSizeInBytes + imageSizeInBytes)
+		{
+		DeleteItem(iVgImageCache.Last());
+		}
+	newItem->iSerialNumber = aBitmap.SerialNumber();
+	newItem->iImage = aImage;
+	newItem->iTouchCount = aBitmap.TouchCount();
+	newItem->iOrigin = aOrigin;
+	newItem->iImageSizeInBytes = imageSizeInBytes;
+	TInt err = iCacheItemMap.Insert(newItem->iSerialNumber, newItem);
+	if (err != KErrNone)
+		{
+		delete newItem;
+		return EFalse;
+		}
+	iVgImageCache.AddFirst(*newItem);
+	iCacheSizeInBytes += newItem->iImageSizeInBytes;
+	return ETrue;
+	}
+
+/**
+Retrieves the VGImage from the cache that was created from the supplied CFbsBitmap.
+The cache is first searched to find the item containing the VGImage that was created from the CFbsBitmap.
+If no matching item is found, no VGImage is returned.
+If the matching item is found, the touch count is checked to determine whether the
+CFbsBitmap has been updated since the stored VGImage was created from it.  If it has, the matching item 
+and VGImage is deleted from the cache and no VGImage is returned.
+If the matching item is found and the CFbsitmap has not been updated sionce the VGImage was created,
+the associated VGImage is returned.
+
+@param aBitmap	The bitmap used to reference the item containing the VGImage.
+@param aOrigin  The origin of the VGImage, relative to the top left corner of the source image.
+
+@return	VG_INVALID_HANDLE if no VGImage exists for the supplied CFbsBitmap or if the stored VGImage is out of date.
+		Otherwise the VGImage associated with the CFbsBitmap is returned.
+ */
+VGImage CVgImageCache::GetVgImageFromBitmap(const CFbsBitmap& aBitmap, const TPoint& aOrigin)
+	{
+	// search through cache to find the item with a matching bitmap ID
+	CVgImageCacheItem** itemPtr = iCacheItemMap.Find(aBitmap.SerialNumber());
+	++iNumMatchTries;
+	if(itemPtr == NULL)
+		{
+		// searched all the way through cache and there is no matching image
+		++iNumMatchMisses;
+		return VG_INVALID_HANDLE;
+		}
+	CVgImageCacheItem* item = *itemPtr;
+	// Check whether the VGImage held by the item is up-to-date
+	// - check touch counts are equal.
+	// - check origins used for creating VGImage are equal.
+	if (aBitmap.TouchCount() != item->iTouchCount || aOrigin != item->iOrigin)
+		{
+		// VGImage in item needs updating, so remove and delete the entry
+		// and return NULL to indicate that a new entry needs to be created.
+		DeleteItem(item);
+		return VG_INVALID_HANDLE;
+		}
+	// VGImage is up-to date.
+	// If item is not already at front of list, move it there
+	if(!iVgImageCache.IsFirst(item))
+		{
+		item->iLink.Deque();
+		iVgImageCache.AddFirst(*item);
+		}
+	return item->iImage;
+	}
+
+// Test APIs
+
+/**
+Determines whether an item exists for a specified bitmap's serial number.
+
+@param aSerialNumber	The unique identifier of a CFbsBitmap.
+
+@return ETrue if a matching item is found using the serial number.  EFalse if not.
+ */
+TBool CVgImageCache::IsInCache(TInt64 aSerialNumber)
+	{
+	return (iCacheItemMap.Find(aSerialNumber) != NULL);
+	}
+
+/**
+The touch count stored in the item associated with the supplied serial number.
+
+@param aSerialNumber	The unique identifier of a CFbsBitmap.
+
+@return	The touch count stored in the item associated with the supplied serial number.
+		KErrNotFound if no matching item is found using the serial number.
+ */
+TInt CVgImageCache::TouchCount(TInt64 aSerialNumber)
+	{
+	CVgImageCacheItem** itemPtr = iCacheItemMap.Find(aSerialNumber);
+	if(itemPtr == NULL)
+		{
+		// searched all the way through cache and there is no matching image
+		return KErrNotFound;
+		}
+	return (*itemPtr)->iTouchCount;
+	}
+
+/**
+The number of entries in the cache.
+@return The number of entries in the cache.
+ */
+TInt CVgImageCache::NumEntries() const
+	{
+	return iCacheItemMap.Count();
+	}
+
+/**
+Returns a list of the serial numbers of all the cache items, with the most-recently used item at ordinal 0
+and the least-recently used item and the end of the list.
+
+@param aSerialNumberList A reference to a list in which to return the serial number list.
+@param aListSize The number of entries allocated for the list.
+ */
+void CVgImageCache::GetOrderedCacheEntries(TInt64& aSerialNumberList, TInt aListSize)
+	{
+	GRAPHICS_ASSERT_ALWAYS(aSerialNumberList, EDirectGdiPanicInvalidPointArray)
+	TDblQueIter<CVgImageCacheItem> iter(iVgImageCache);
+
+	TInt n = iCacheItemMap.Count();
+	// If n is greater than number of entries in list, restrict to number of entries.
+	if (n > aListSize) n = aListSize;
+	for (TInt ii = 0; ii < n; ++ii)
+		{
+		CVgImageCacheItem* item = iter++;
+		(&aSerialNumberList)[ii] = item->iSerialNumber;
+		}
+	
+	// If n is less than number of entries in list, pad out entries with 0
+	// (i.e. invlaid serial numbers)
+	while (n < aListSize)
+		{
+		(&aSerialNumberList)[n++] = 0;
+		}
+	}
+
+/**
+The total size of the cache in bytes.
+@return The total size of the cache in bytes.
+ */
+TInt CVgImageCache::CacheSizeInBytes() const
+	{
+	return iCacheSizeInBytes;
+	}
+
+/**
+The maximum size of the cache in bytes.
+@return The maximum size of the cache in bytes.
+ */
+TInt CVgImageCache::MaxCacheSize() const
+	{
+	return iMaxCacheSizeInBytes;
+	}
+
+/**
+Resets the cache. Iterates through all the items in the cache and deletes them.
+ */
+void CVgImageCache::ResetCache()
+	{
+	// cycle through all the items and destroy the VGImages.
+	TDblQueIter<CVgImageCacheItem> iter(iVgImageCache);
+	CVgImageCacheItem* item;
+	while((item=iter++)!=NULL)
+		{
+		DeleteItem(item);
+		}
+	}
+
+/**
+Sets the maximum size in bytes of the cache. Checks the current size of the
+cache and sets the maximum cache size if the current cache size is smaller 
+or equal to aCacheSize.
+@param aMaxCacheSize The maximum size in bytes to allow for the cache.
+@return KErrNone if the maximum cache size has been changed successfully,
+KErrArgument if aMaxCacheSize is smaller than the current cache size.
+ */
+TInt CVgImageCache::SetMaxCacheSize(TInt aMaxCacheSize)
+	{
+	if (iCacheSizeInBytes <= aMaxCacheSize) 
+		{
+		iMaxCacheSizeInBytes = aMaxCacheSize;
+		return KErrNone;
+		}
+	
+	return KErrArgument;
+	}