os/graphics/graphicscomposition/openwftest/src/surfaceutility.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2010 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 /**
    17  @file
    18 */
    19 
    20 #include <e32std.h>
    21 #include <imageconversion.h>
    22 #include <stdlib.h>
    23 #include <s32file.h> 
    24 #include "surfaceutility.h"
    25 
    26 #ifdef __cplusplus
    27 extern "C" {
    28 #endif
    29 
    30 WFC_API_CALL WFCNativeStreamType WFC_APIENTRY
    31 extwfcGetOnScreenStream(WFCDevice dev, WFCContext context) WFC_APIEXIT;
    32 
    33 #ifdef __cplusplus
    34 }
    35 #endif
    36 
    37 CSurfaceUtility::CSurfaceUtility()
    38 : iSurfaces(NULL)
    39 	{
    40 	}
    41 	
    42 CSurfaceUtility* CSurfaceUtility::NewL()
    43 	{
    44 	CSurfaceUtility* utility = new (ELeave)CSurfaceUtility();
    45 	CleanupStack::PushL(utility);
    46 	utility->ConstructL();
    47 	CleanupStack::Pop(utility);
    48 	return utility;
    49 	}
    50 	
    51 void CSurfaceUtility::ConstructL()
    52 	{
    53 	TInt r = iManager.Open();
    54 	if (r != KErrNone)
    55 		{
    56 		LOG(("Surface manager failed to open: %d", r));
    57 		User::Leave(r);
    58 		}
    59 	
    60 	r = iSurfaceUpdateSession.Connect();
    61 	if (r != KErrNone)
    62 		{
    63 		LOG(("Failed to connect to update server: %d", r));
    64 		User::Leave(r);
    65 		}	
    66 	}
    67 
    68 CSurfaceUtility::~CSurfaceUtility()
    69 	{
    70 	DestroyAll();
    71 
    72 	iSurfaces.Close();
    73 
    74 	iManager.Close();
    75 
    76 	iSurfaceUpdateSession.Close();	
    77 	}
    78 
    79 TBool CSurfaceUtility::DestroyAll()
    80 	{
    81 	TInt err = 	KErrNone;
    82 	TInt jj = iSurfaces.Count() - 1;
    83 	if (jj<0)
    84 		return EFalse;
    85 	for (; jj >= 0; jj--)
    86 		{
    87 		err = iManager.CloseSurface(iSurfaces[jj]);
    88 		if (err!=KErrNone)
    89 			{
    90 			LOG(("Error closing surface: 0x%X\n", err));
    91 			}
    92 		TInt offset;
    93 		err = iManager.GetBufferOffset(iSurfaces[jj],0,offset);
    94 		if (err==KErrNone)
    95 		    {
    96             LOG(("Error: closed surface still accessible: index %i surface %08X %08X %08X %08X\n", jj, iSurfaces[jj]));
    97 		    }
    98 		}
    99 	iSurfaces.Reset();
   100 	return ETrue;
   101 	}
   102 
   103 /***************************************
   104  * The aim of the THeapSurfaceArray is to locally switch in the specified heap for any array operation
   105  ***************************************/
   106 
   107 CSurfaceUtility::RHeapSurfaceArray::RHeapSurfaceArray(RHeapSurfaceArray* aUseExternalArray)
   108 	:	iUseArray(aUseExternalArray?aUseExternalArray->iUseArray:&this->iLocalArray),
   109 	iExternalHeapRef(aUseExternalArray?aUseExternalArray->iExternalHeapRef:User::Heap())
   110 	{
   111 	
   112 	}
   113 /************************************
   114  * The following methods have been used by the surfaceutility... some require the heap wrapping, and some don't
   115  * Three strategies are needed for 7 methods...
   116  * Some methods only read the existing objects, so don't need a heap swap at all
   117  * Leaving methods have to use PopAndDestroy strategy to restore the heap on leaving or success
   118  * Non-leaving methods must not call PushL, so directly make SwitchHeap calls!
   119  ************************************/
   120 
   121 // PopAndDestroy method to restore the heap
   122 /*static*/ void	CSurfaceUtility::RHeapSurfaceArray::PopHeap(void* aHeapPtr)
   123 	{
   124 	RHeap* heapPtr=(RHeap*)aHeapPtr;
   125 	User::SwitchHeap(heapPtr);
   126 	}
   127 
   128 TSurfaceId& CSurfaceUtility::RHeapSurfaceArray::operator[](TUint aIndex)
   129 	{
   130 	return iUseArray->operator[](aIndex);
   131 	}
   132 
   133 // Close only closes the local array, while Reset resets the active array (may be external)
   134 void CSurfaceUtility::RHeapSurfaceArray::Close()
   135 	{
   136 	iLocalArray.Close();
   137 	}
   138 
   139 TInt CSurfaceUtility::RHeapSurfaceArray::Count() const
   140 	{
   141 	return iUseArray->Count();
   142 	}
   143 
   144 // Close only closes the local array, while Reset resets the active array (may be external)
   145 inline void CSurfaceUtility::RHeapSurfaceArray::Reset()
   146 	{
   147 	iUseArray->Reset();
   148 	}
   149 
   150 void CSurfaceUtility::RHeapSurfaceArray::AppendL(const TSurfaceId &anEntry)
   151 	{
   152 	iUseArray->AppendL(anEntry);
   153 	}
   154 
   155 TInt CSurfaceUtility::RHeapSurfaceArray::Find(const TSurfaceId &anEntry) const
   156 	{
   157 	return iUseArray->Find(anEntry);
   158 	}
   159 
   160 void CSurfaceUtility::RHeapSurfaceArray::Remove(TInt anIndex)
   161 	{
   162 	iUseArray->Remove(anIndex);
   163 	}
   164 
   165 /**
   166 Cleanup stack helper object, holding references to both utility and surface, so
   167 that the standard Close() semantics can be used.
   168 */
   169 class TSurfaceCleanup
   170 	{
   171 public:
   172 	TSurfaceCleanup(CSurfaceUtility& aUtility, TSurfaceId& aSurface)
   173 		: iUtility(aUtility), iSurface(aSurface)
   174 		{}
   175 	void Close()
   176 		{
   177 		// Removes the surface from the list of surfaces to clean up, and closes
   178 		// the surface reference.
   179 		iUtility.DestroySurface(iSurface);
   180 		}
   181 private:
   182 	CSurfaceUtility& iUtility;
   183 	TSurfaceId& iSurface;
   184 	};
   185 
   186 /**
   187 Get the size of a surface.
   188 
   189 @param aSurface The surface to get the size for.
   190 @return The size in pixels, or empty on failure.
   191 */
   192 TSize CSurfaceUtility::SurfaceSize(const TSurfaceId& aSurface)
   193 	{
   194 	RSurfaceManager::TInfoBuf infoBuf;
   195 	RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
   196 
   197 	if (iManager.SurfaceInfo(aSurface, infoBuf) == KErrNone)
   198 		{
   199 		return info.iSize;
   200 		}
   201 
   202 	return TSize();
   203 	}
   204 
   205 /**
   206 Create a surface using the surface manager.
   207 
   208 Stores the ID for tear down, as well as returning it.
   209 
   210 @param aSize Dimensions of the surface.
   211 @param aPixelFormat	UID of the pixel format.
   212 @param aStride	Stride value for the surface (usually bytes per pixel * width)
   213 @param aContiguous  Contiguous flag for creating surfaces
   214 @param aBuffers Number of buffers in the surface
   215 @leave May leave due to lack of memory.
   216 @return New surface's ID.
   217 */
   218 TSurfaceId CSurfaceUtility::CreateSurfaceL(const TSize& aSize, TUidPixelFormat aPixelFormat, TInt aStride, TBool aContiguous, TInt aBuffers)
   219 	{
   220 	RSurfaceManager::TSurfaceCreationAttributesBuf bf;
   221 	RSurfaceManager::TSurfaceCreationAttributes& b = bf();
   222 	if (aStride<aSize.iWidth*BytesPerPixelL(aPixelFormat))
   223 	    {
   224 	    User::Leave(KErrOverflow);
   225 	    }
   226 	b.iSize.iWidth = aSize.iWidth;
   227 	b.iSize.iHeight = aSize.iHeight;
   228 	b.iBuffers = aBuffers;				// number of buffers in the surface
   229 	b.iPixelFormat = aPixelFormat;
   230 	b.iStride = aStride;		// Number of bytes between start of one line and start of next
   231 	b.iOffsetToFirstBuffer = 0;	// way of reserving space before the surface pixel data
   232 	b.iAlignment = 4;			// alignment, 1,2,4,8 byte aligned
   233 	b.iContiguous = aContiguous;
   234 	b.iMappable = ETrue;
   235 
   236 	TSurfaceId surface = TSurfaceId::CreateNullId();
   237 
   238 	User::LeaveIfError(iManager.CreateSurface(bf, surface));
   239 	iSurfaces.AppendL(surface);
   240 	return surface;
   241 	}
   242 
   243 /**
   244 A helper function that returns the bytes per pixel for a given pixel format uid
   245 
   246 @param aPixelFormat Pixel format UID to convert
   247 @return The bytes per pixel
   248 */
   249 TInt CSurfaceUtility::BytesPerPixelL(TUidPixelFormat aPixelFormat)
   250 	{
   251 	TInt bytesPerPixel = 0;
   252 	switch (aPixelFormat)
   253 		{
   254 		case EUidPixelFormatXRGB_8888:
   255 		case EUidPixelFormatARGB_8888:
   256 		case EUidPixelFormatARGB_8888_PRE:
   257 			{
   258 			bytesPerPixel = 4;
   259 			break;
   260 			}
   261 		case EUidPixelFormatXRGB_4444:
   262 		case EUidPixelFormatARGB_4444:
   263 		case EUidPixelFormatRGB_565:
   264 			{
   265 			bytesPerPixel = 2;
   266 			break;
   267 			}
   268 		default:
   269 			{
   270 			User::Leave(KErrNotSupported);
   271 			break;
   272 			}
   273 		}
   274 	return bytesPerPixel;
   275 	}
   276 
   277 /**
   278 Fill buffer 0 of the given surface with a color.
   279 
   280 @param aSurface	The surface to be filled.
   281 @param aColor	The color to fill it with.
   282 */
   283 void CSurfaceUtility::FillSurfaceL(TSurfaceId& aSurface, const TRgb& aColor)
   284 	{
   285     FillSurfaceL(aSurface, 0, aColor);
   286 	}
   287 
   288 /**
   289 Fill a specified buffer number of the given surface with a color.
   290 
   291 @param aSurface	The surface to be filled.
   292 @param aBuffer 	The buffer to fill.
   293 @param aColor	The color to fill it with.
   294 */
   295 void CSurfaceUtility::FillSurfaceL(TSurfaceId& aSurface, TInt aBuffer, const TRgb& aColor)
   296 	{
   297 	RSurfaceManager::TInfoBuf infoBuf;
   298 	RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
   299 
   300 	User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
   301 	TUint32 color = 0;
   302 	TBool use16 = EFalse;
   303 	TInt numBuffers = info.iBuffers;
   304 	if (aBuffer < 0 || aBuffer >= numBuffers)
   305 		{
   306 		User::Leave(KErrArgument);
   307 		}
   308 
   309 	if (info.iSize.iHeight<0 || info.iSize.iWidth<0 || info.iStride<0)
   310 		{
   311 		User::Leave(KErrCorrupt);
   312 		}
   313 	if (info.iSize.iHeight==0 || info.iSize.iWidth==0 || info.iStride==0)
   314 		{
   315 		User::Leave(KErrNotReady);
   316 		}
   317 
   318 	switch (info.iPixelFormat)
   319 		{
   320 		case EUidPixelFormatXRGB_8888:
   321 			{
   322 			color = aColor.Color16MU();
   323 			break;
   324 			}
   325 		case EUidPixelFormatARGB_8888:
   326 			{
   327 			color = aColor.Color16MA();
   328 			break;
   329 			}
   330 		case EUidPixelFormatARGB_8888_PRE:
   331 			{
   332 			color = aColor.Color16MAP();
   333 			break;
   334 			}
   335 		case EUidPixelFormatXRGB_4444:
   336 		case EUidPixelFormatARGB_4444:
   337 			{
   338 			color = aColor.Color4K();
   339 			use16 = ETrue;
   340 			break;
   341 			}
   342 		case EUidPixelFormatRGB_565:
   343 			{
   344 			color = aColor.Color64K();
   345 			use16 = ETrue;
   346 			break;
   347 			}
   348 		default:
   349 			{
   350 			User::Leave(KErrNotSupported);
   351 			break;
   352 			}
   353 		}
   354 
   355 	RChunk chunk;
   356 	User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
   357 	CleanupClosePushL(chunk);
   358 
   359 	TInt offsetToBuffer;
   360 	User::LeaveIfError(iManager.GetBufferOffset(aSurface, aBuffer, offsetToBuffer));
   361 	TUint8* surfacePtr = chunk.Base() + offsetToBuffer;
   362 	TUint8* linePtr = surfacePtr;
   363 
   364 	if (use16)
   365 		{
   366 		if ( info.iSize.iWidth*2>info.iStride)
   367 			{
   368 			User::Leave(KErrOverflow);
   369 			}
   370 		TUint16* ptr = reinterpret_cast<TUint16*>(surfacePtr);
   371 
   372 		// Fill first line
   373 		for (TInt xx = 0; xx < info.iSize.iWidth; xx++)
   374 			{
   375 			ptr[xx] = (TUint16)color;
   376 			}
   377 		}
   378 	else
   379 		{
   380 		if ( info.iSize.iWidth*4>info.iStride)
   381 			{
   382 			User::Leave(KErrOverflow);
   383 			}
   384 		TUint32* ptr = reinterpret_cast<TUint32*>(surfacePtr);
   385 
   386 		// Fill first line
   387 		for (TInt xx = 0; xx < info.iSize.iWidth; xx++)
   388 			{
   389 			ptr[xx] = color;
   390 			}
   391 		}
   392 
   393 	// Now copy that to the other lines
   394 	for (TInt yy = 1; yy < info.iSize.iHeight; yy++)
   395 		{
   396 		linePtr += info.iStride;
   397 		Mem::Copy(linePtr, surfacePtr, info.iSize.iWidth * BytesPerPixelL(info.iPixelFormat));
   398 		}
   399 	
   400 	CleanupStack::PopAndDestroy(/* chunk */);
   401 	}
   402 
   403 /**
   404 Destroy a surface.
   405 
   406 As well as destroying the surface, it is removed from the set held for
   407 destruction during tear down.
   408 
   409 @param aSurface	The surface to be destroyed.
   410 */
   411 void CSurfaceUtility::DestroySurface(TSurfaceId& aSurface)
   412 	{
   413 	TInt index = iSurfaces.Find(aSurface);
   414 	
   415 	if (index != KErrNotFound)
   416 		{
   417 		iSurfaces.Remove(index);
   418 		}
   419 
   420 	TInt err = iManager.CloseSurface(aSurface);
   421 	if (err!=KErrNone)
   422 		LOG(("Error closing surfaces: 0x%X\n", err));
   423 	}
   424 
   425 /**
   426 Get surface header information
   427 
   428 @param aSurface A surface to get the header info from.
   429 @param aInfo Returned package info of the surface header.
   430 
   431 @return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface,
   432 KErrAccessDenied if the surface is not open in the current process, otherwise a system wide
   433 error code.
   434  */
   435 TInt CSurfaceUtility::GetHeader(const TSurfaceId& aSurface, RSurfaceManager::TInfoBuf& aInfo) 
   436     {
   437     return iManager.SurfaceInfo(aSurface, aInfo);
   438     }
   439 
   440 /**
   441 Get buffer pointer to a surface
   442 
   443 @param aSurface Surface of the buffer pointer.
   444 @param aNumOfBuffer A number of buffer.
   445 @param aChunk A chunk of memory.
   446 
   447 @return A buffer pointer of the surface.
   448  */
   449 TUint8* CSurfaceUtility::GetBufferPointerL(const TSurfaceId& aSurface, TInt aNumOfBuffer, RChunk& aChunk) 
   450     {
   451     TInt offsetToBuffer;
   452     User::LeaveIfError(iManager.MapSurface(aSurface, aChunk));
   453     User::LeaveIfError(iManager.GetBufferOffset(aSurface, aNumOfBuffer, offsetToBuffer));
   454     TUint8* surfacePtr = aChunk.Base() + offsetToBuffer;
   455     return surfacePtr;
   456     }
   457 
   458 /**
   459 Get pixel color at a position.
   460 
   461 @param aInfo Package info of a surface.
   462 @param aPixelData Surface buffer pointer.
   463 @param aPosition Position of the pixel.
   464 
   465 @return Color of the pixel position.
   466 */
   467 TRgb CSurfaceUtility::GetPixelL(RSurfaceManager::TInfoBuf& aInfo, TAny* aPixelData, TPoint aPosition) 
   468     {
   469     RSurfaceManager::TSurfaceInfoV01& info = aInfo();
   470     TInt stride = info.iStride;
   471     TUidPixelFormat pixelFormat = info.iPixelFormat;
   472     TInt bytesPerPixel = BytesPerPixelL(pixelFormat);
   473     TInt pixelStride = stride / bytesPerPixel;
   474     TUint pixel = aPosition.iY * pixelStride + aPosition.iX;
   475     TUint* pixels = reinterpret_cast< TUint* >( aPixelData );
   476     TRgb colour;
   477     colour.SetInternal(pixels[ pixel ]);
   478     return colour;
   479     }
   480 
   481 /**
   482 Check pixel color within a rectangle is as expected.
   483 It checks every color channel of every pixel within the rectangle.
   484 
   485 @param aSurface The surface to be checked.
   486 @param aRect The rectangle for pixel checking.
   487 @param aNumOfBuffer Number of buffer.
   488 @param aExpectedColor The expected color.
   489 @param aTolerance A tolerance value.
   490 
   491 @return EFalse if a color channel of a pixel is outside the tolerance range. 
   492         ETrue if all pixel colors are within the tolerance range.
   493 */
   494 TBool CSurfaceUtility::CheckRectColor(const TSurfaceId& aSurface, TRect& aRect, TInt aNumOfBuffer, const TRgb& aExpectedColor, TInt aTolerance) 
   495     {
   496     RSurfaceManager::TInfoBuf infoBuf;
   497     RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
   498     TInt error = GetHeader(aSurface, infoBuf);
   499     if (error != KErrNone)
   500     	{
   501 		RDebug::Printf("Line %d GetHeader failed",__LINE__);
   502 		return EFalse;
   503     	}
   504 
   505     RChunk chunk;
   506     TUint8* surfacePtr = NULL;
   507     TRAP_IGNORE(surfacePtr = GetBufferPointerL(aSurface, aNumOfBuffer, chunk));
   508     if (!surfacePtr)
   509     	{
   510 		RDebug::Printf("Line %d GetBufferPointerL failed",__LINE__);
   511 		return EFalse;
   512     	}
   513     
   514     TRgb color;
   515     // Check every colour channel of every pixel is within the tolerance
   516     for (TInt ii = aRect.iTl.iX; ii < aRect.iBr.iX; ++ii)
   517         {
   518         for (TInt jj = aRect.iTl.iY; jj < aRect.iBr.iY; ++jj)
   519             {
   520             color = GetPixelL(infoBuf, surfacePtr, TPoint(ii, jj));      
   521             TBool checkR = (color.Red() <= (aExpectedColor.Red() + aTolerance) && color.Red() >= (aExpectedColor.Red() - aTolerance));
   522             TBool checkG = (color.Green() <= (aExpectedColor.Green() + aTolerance) && color.Green() >= (aExpectedColor.Green() - aTolerance));
   523             TBool checkB = (color.Blue() <= (aExpectedColor.Blue() + aTolerance) && color.Blue() >= (aExpectedColor.Blue() - aTolerance));
   524             if (!checkR || !checkG || !checkB)
   525                 {
   526                 RDebug::Printf("At x=%d y=%d CheckRectColor has failed:",ii,jj);
   527                 RDebug::Printf("Expected Red %d - Actual Red %d",aExpectedColor.Red(),color.Red());
   528                 RDebug::Printf("Expected Green %d - Actual Green %d",aExpectedColor.Green(),color.Green());
   529                 RDebug::Printf("Expected Blue %d - Actual Blue %d",aExpectedColor.Blue(),color.Blue());
   530                 return EFalse;            
   531                 }               
   532             }
   533         }
   534     return ETrue;
   535     }
   536 
   537 /**
   538 Save on screen image to a .tga file
   539 
   540 @param aSurface A surface to be saved
   541 @param aBufferNumber The surface's buffer number
   542 @param aDestination The path and name of the tga to save eg c:\\test\\img\\image1.tga
   543 @return ETrue on successful calls
   544         Fails if GetBufferPointerL returns NULL pointer
   545  */
   546 TBool CSurfaceUtility::SaveResultImageTGAL(const TSurfaceId& aSurface, TInt aBufferNumber, TDesC& aDestination)
   547     {
   548     RSurfaceManager::TInfoBuf infoBuf;
   549     RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
   550     User::LeaveIfError(GetHeader(aSurface, infoBuf));
   551     TInt stride = info.iStride;
   552     TSize surfaceSize = info.iSize;
   553     TUidPixelFormat pixelFormat = info.iPixelFormat;
   554     TInt bytesPerPixel = BytesPerPixelL(pixelFormat);
   555     TInt widthInBytes = surfaceSize.iWidth * bytesPerPixel;
   556     
   557     RFs fs;
   558     User::LeaveIfError(fs.Connect());
   559     CleanupClosePushL(fs); 
   560         
   561     // Create image file
   562     RFileWriteStream fstream;
   563     User::LeaveIfError(fstream.Replace(fs, aDestination, EFileShareAny|EFileWrite));
   564     CleanupClosePushL(fstream); 
   565     
   566     // Write header
   567     fstream.WriteUint8L(0);                 // ID Length
   568     fstream.WriteUint8L(0);                 // Color map type
   569     fstream.WriteUint8L(2);                 // Image type - Uncompressed, True-color Image
   570     fstream.WriteUint32L(0);                // Color map specification 5 bytes
   571     fstream.WriteUint8L(0);                 // Color map specification
   572     fstream.WriteUint32L(0);                // Image specification - origin of image
   573     fstream.WriteUint16L(static_cast<TUint16>(surfaceSize.iWidth));      // Image specification - Image width
   574     fstream.WriteUint16L(static_cast<TUint16>(surfaceSize.iHeight));     // Image specification - Image height
   575     fstream.WriteUint8L(32);                // Image specification - Pixel Depth (bits per pixel)
   576     fstream.WriteUint8L(1 << 5);            // Image specification - Image Descriptor, Screen destination of first pixel is top left 
   577 
   578     RChunk chunk;
   579     TUint8* surfacePtr = GetBufferPointerL(aSurface, aBufferNumber, chunk);
   580     if(surfacePtr == NULL)
   581         {
   582         CleanupStack::PopAndDestroy(2); 
   583         return EFalse;
   584         }
   585     
   586     // Write image line by line
   587     for(TInt ii = 0; ii < surfaceSize.iHeight; ++ii)
   588         {
   589         fstream.WriteL(surfacePtr, widthInBytes); 
   590         surfacePtr += stride;
   591         }
   592 
   593     fstream.CommitL();
   594     chunk.Close();
   595     CleanupStack::PopAndDestroy(2); 
   596     
   597     return ETrue;
   598     }
   599 
   600 /**
   601 Create directory for images to be saved
   602 
   603 @param aDir Directory for images to be saved
   604 @return ETrue on success
   605  */
   606 TBool CSurfaceUtility::CreateImagePath(TDesC& aDir)
   607     {
   608     RFs fs;
   609     TInt err = fs.Connect();
   610     if (err == KErrNone)
   611         {
   612         err = fs.MkDirAll(aDir);
   613         if (err == KErrAlreadyExists)
   614             {
   615             err = KErrNone;
   616             }
   617         fs.Close();
   618         }
   619     return (err == KErrNone);
   620     }
   621     
   622 /**
   623 Submit an update to a surface to the update server.
   624 
   625 @param aSurface	The surface which has been updated.
   626 @param aRegion	The area of the surface affected, or NULL for all of it.
   627 */
   628 TInt CSurfaceUtility::SubmitUpdate(const TSurfaceId& aSurface,TInt aBufferNumber, const TRegion* aRegion)
   629 	{
   630 	if (!iSurfaceUpdateSession.Handle())
   631 	    {
   632 	    iSurfaceUpdateSession.Connect();
   633 	    }
   634     if (!iSurfaceUpdateSession.Handle())
   635         {
   636         LOG(("Error - SUS client not started!"));
   637         return KErrNotReady;
   638         }
   639     else
   640         {
   641         TInt err =iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, aBufferNumber, aRegion); 
   642         if (err!=KErrNone)
   643             LOG(("Error submitting update: 0x%X\n", err));
   644         return err;
   645         }
   646 	}
   647 
   648 void CSurfaceUtility::NotifyWhenDisplayed(TRequestStatus& aStatusDisplayed, TTimeStamp& aTimeStamp)
   649     {
   650     iSurfaceUpdateSession.NotifyWhenDisplayed(aStatusDisplayed, aTimeStamp);
   651     }
   652 
   653 void CSurfaceUtility::NotifyWhenDisplayedXTimes(TInt aCount, TRequestStatus& aStatusDisplayedX)
   654     {
   655     iSurfaceUpdateSession.NotifyWhenDisplayedXTimes(aCount, aStatusDisplayedX);
   656     }
   657 
   658 void CSurfaceUtility::NotifyWhenAvailable(TRequestStatus& aStatusAvailable)
   659     {
   660     iSurfaceUpdateSession.NotifyWhenAvailable(aStatusAvailable);
   661     }
   662 
   663 SymbianStreamType CSurfaceUtility::GetOnScreenStream(WFCDevice aDev, WFCContext aContext)
   664     {
   665     return reinterpret_cast<SymbianStreamType>(wfcGetOnScreenStream(aDev, aContext));
   666     }
   667 
   668 
   669