os/graphics/graphicscomposition/openwfcompositionengine/test/tscreeninterface/streamutility.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     2 //
     3 // Permission is hereby granted, free of charge, to any person obtaining a
     4 // copy of this software and/or associated documentation files (the
     5 // "Materials"), to deal in the Materials without restriction, including
     6 // without limitation the rights to use, copy, modify, merge, publish,
     7 // distribute, sublicense, and/or sell copies of the Materials, and to
     8 // permit persons to whom the Materials are furnished to do so, subject to
     9 // the following conditions:
    10 //
    11 // The above copyright notice and this permission notice shall be included
    12 // in all copies or substantial portions of the Materials.
    13 //
    14 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    17 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    18 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    19 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    20 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    21 //
    22 // Description:
    23 //
    24 
    25 /**
    26  @file
    27 */
    28 
    29 #include <e32std.h>
    30 #include <imageconversion.h>
    31 #include <graphics/symbianstream.h>
    32 #include "streamutility.h"
    33 
    34 #define WFC_INVALID_HANDLE NULL
    35 
    36 CStreamUtility::CStreamUtility()
    37 	{
    38 	}
    39 	
    40 CStreamUtility* CStreamUtility::NewL()
    41 	{
    42 	CStreamUtility* utility = new (ELeave)CStreamUtility();
    43 	CleanupStack::PushL(utility);
    44 	utility->ConstructL();
    45 	CleanupStack::Pop(utility);
    46 	return utility;
    47 	}
    48 	
    49 void CStreamUtility::ConstructL()
    50 	{
    51 	TInt r = iManager.Open();
    52 	if (r != KErrNone)
    53 		{
    54 		LOG(("Surface manager failed to open: %d", r));
    55 		User::Leave(r);
    56 		}
    57 	}
    58 	
    59 CStreamUtility::~CStreamUtility()
    60 	{
    61 	DestroyAll();
    62 
    63 	iStreams.Close();
    64 
    65 	iManager.Close();
    66 	}
    67 
    68 TBool CStreamUtility::DestroyAll()
    69 	{
    70 	TInt err = 	KErrNone;
    71 	TInt jj = iStreams.Count() - 1;
    72 	if (jj<0)
    73 		return EFalse;
    74 	for (; jj >= 0; jj--)
    75 		{
    76         //The following lines are just to get the surface ID for verification
    77 		SymbianStreamBuffer bufferHandle;
    78 		User::LeaveIfError(SymbianStreamAcquireReadBuffer(iStreams[jj], &bufferHandle));
    79 		long bufferIndex;
    80 		const TSurfaceId* pSurfaceId = NULL;
    81 		
    82 		User::LeaveIfError(SymbianStreamGetBufferId(iStreams[jj],bufferHandle,&bufferIndex,&pSurfaceId));
    83         User::LeaveIfError(SymbianStreamReleaseReadBuffer(iStreams[jj], bufferHandle));
    84         
    85         const TSurfaceId surfaceId = *pSurfaceId;   //Need to copy my reference to the ID.
    86         //Actually release the stream
    87         SymbianStreamRemoveReference(iStreams[jj]);
    88         
    89         //Verify the stream is now not accessible
    90         TInt offset;
    91 		err = iManager.GetBufferOffset(surfaceId,0,offset);
    92 		if (err==KErrNone)
    93 			{
    94 			LOG(("Closing stream via DestoryAll did not destroy surface!"));
    95 			}
    96 		}
    97 	iStreams.Reset();
    98 	return ETrue;
    99 	}
   100 
   101 /***************************************
   102  * The aim of the RHeapStreamArray is to locally switch in the specified heap for any array operation
   103  ***************************************/
   104 
   105 CStreamUtility::RHeapStreamArray::RHeapStreamArray(RHeapStreamArray* aUseExternalArray)
   106 	:	iUseArray(aUseExternalArray?aUseExternalArray->iUseArray:&this->iLocalArray),
   107 	iExternalHeapRef(aUseExternalArray?aUseExternalArray->iExternalHeapRef:User::Heap())
   108 	{
   109 	
   110 	}
   111 /************************************
   112  * The following methods have been used by the streamutility... some require the heap wrapping, and some don't
   113  * I actually need three different strategies (count em) for 7 methods...
   114  * Some methods only read the existing objects, so don't need a heap swap at all
   115  * Leaving methods have to use PopAndDestroy strategy to restore the heap on leaving or success
   116  * Non-leaving methods must not call PushL, so directly make SwitchHeap calls!
   117  ************************************/
   118 
   119 /// PopAndDestroy method to restore the heap
   120 /*static*/ void	CStreamUtility::RHeapStreamArray::PopHeap(void* aHeapPtr)
   121 	{
   122 	RHeap* heapPtr=(RHeap*)aHeapPtr;
   123 	User::SwitchHeap(heapPtr);
   124 	}
   125 
   126 SymbianStreamType& CStreamUtility::RHeapStreamArray::operator[](TUint aIndex)
   127 	{
   128 	return iUseArray->operator[](aIndex);
   129 	}
   130 
   131 /// Close only closes the local array, while Reset resets the active array (may be external)
   132 void CStreamUtility::RHeapStreamArray::Close()
   133 	{
   134 	iLocalArray.Close();
   135 	}
   136 
   137 TInt CStreamUtility::RHeapStreamArray::Count() const
   138 	{
   139 	return iUseArray->Count();
   140 	}
   141 
   142 /// Close only closes the local array, while Reset resets the active array (may be external)
   143 inline void CStreamUtility::RHeapStreamArray::Reset()
   144 	{
   145 	iUseArray->Reset();
   146 	}
   147 
   148 void CStreamUtility::RHeapStreamArray::AppendL(const SymbianStreamType &anEntry)
   149 	{
   150 	iUseArray->AppendL(anEntry);
   151 	}
   152 
   153 TInt CStreamUtility::RHeapStreamArray::Find(const SymbianStreamType &anEntry) const
   154 	{
   155 	return iUseArray->Find(anEntry);
   156 	}
   157 
   158 void CStreamUtility::RHeapStreamArray::Remove(TInt anIndex)
   159 	{
   160 	iUseArray->Remove(anIndex);
   161 	}
   162 
   163 /**
   164 Cleanup stack helper object, holding references to both utility and stream, so
   165 that the standard Close() semantics can be used.
   166 */
   167 class TStreamCleanup
   168 	{
   169 public:
   170 	TStreamCleanup(CStreamUtility& aUtility, SymbianStreamType& aStream)
   171 		: iUtility(aUtility), iStream(aStream)
   172 		{}
   173 	void Close()
   174 		{
   175 		// Removes the stream from the list of streams to clean up, and closes
   176 		// the stream reference.
   177 		iUtility.DestroyStream(iStream);
   178 		}
   179 private:
   180 	CStreamUtility& iUtility;
   181 	SymbianStreamType& iStream;
   182 	};
   183 
   184 /**
   185 Get the size of a stream.
   186 
   187 @param  aStream The stream to get the size for.
   188 @return The size in pixels, or empty on failure.
   189 */
   190 TSize CStreamUtility::StreamSize(const SymbianStreamType aStream)
   191 	{
   192 	khronos_int32_t width;
   193 	khronos_int32_t height;
   194 	khronos_int32_t stride;
   195 	khronos_int32_t format;
   196 	khronos_int32_t pixelSize;
   197 		
   198 	SymbianStreamGetHeader(aStream, &width, &height, &stride, &format, &pixelSize);
   199 	
   200 	TSize size = TSize(static_cast<TInt>(width), static_cast<TInt>(height));
   201 	
   202 	return size;
   203 	}
   204 
   205 /**
   206 Create a stream using the surface manager.
   207 
   208 Stores the ID for tear down, as well as returning it.
   209 
   210 @param aSize            Dimensions of the stream.
   211 @param aPixelFormat	    UID of the pixel format.
   212 @param aStride	        Stride value for the stream (usually bytes per pixel * width)
   213 @param aReturnSurface   Returns TSurfaceId wrapped by the stream
   214 @param aContiguous      Contiguous flag for creating surfaces
   215 @param aBuffers         Number of buffers
   216 @leave May leave due to lack of memory.
   217 @return New stream's ID.
   218 */
   219 SymbianStreamType CStreamUtility::CreateStreamL(const TSize& aSize, TUidPixelFormat aPixelFormat, 
   220                                             TInt aStride, TSurfaceId& aReturnSurface, 
   221                                             TBool aContiguous, TInt aBuffers)
   222 	{
   223 	RSurfaceManager::TSurfaceCreationAttributesBuf bf;
   224 	RSurfaceManager::TSurfaceCreationAttributes& b = bf();
   225 	if (aStride<aSize.iWidth*BytesPerPixelL(aPixelFormat))
   226 	    {
   227 	    User::Leave(KErrOverflow);
   228 	    }
   229 	b.iSize.iWidth = aSize.iWidth;
   230 	b.iSize.iHeight = aSize.iHeight;
   231 	b.iBuffers = aBuffers;				// number of buffers in the surface
   232 	b.iPixelFormat = aPixelFormat;
   233 	b.iStride = aStride;		// Number of bytes between start of one line and start of next
   234 	b.iOffsetToFirstBuffer = 0;	// way of reserving space before the surface pixel data
   235 	b.iAlignment = 4;			// alignment, 1,2,4,8 byte aligned
   236 	b.iContiguous = !!aContiguous;
   237 	b.iMappable = ETrue;
   238 
   239 	aReturnSurface = TSurfaceId::CreateNullId();
   240 
   241 	User::LeaveIfError(iManager.CreateSurface(bf, aReturnSurface));
   242 	
   243 	SymbianStreamType ns;
   244 	TInt err = SymbianStreamAcquire(&aReturnSurface, &ns);
   245     iManager.CloseSurface(aReturnSurface);		//The stream should now own the only reference
   246 	if (err != KErrNone)
   247 		{
   248 		User::Leave(err);	
   249 		}
   250 	iStreams.AppendL(ns);
   251 	return ns;
   252 	}
   253 
   254 /**
   255 Fill the given stream with a color.
   256 
   257 @param aStream	The stream to be filled.
   258 @param aColor	The color to fill it with.
   259 */
   260 void CStreamUtility::FillStreamL(SymbianStreamType aStream, const TRgb& aColor)
   261 	{
   262 	
   263 	khronos_int32_t width;
   264 	khronos_int32_t height;
   265 	khronos_int32_t stride;
   266 	khronos_int32_t format;
   267 	khronos_int32_t pixelSize;
   268 		
   269 	SymbianStreamGetHeader(aStream, &width, &height, &stride, &format, &pixelSize);
   270 
   271 	TUint32 color = 0;
   272 	TBool use16 = EFalse;
   273 
   274 	if (height<0 || width<0 || stride<0)
   275 		{
   276 		User::Leave(KErrCorrupt);
   277 		}
   278 	if (height==0 || width==0 || stride==0)
   279 		{
   280 		User::Leave(KErrNotReady);
   281 		}
   282 
   283 	switch (format)
   284 		{
   285 		case EUidPixelFormatXRGB_8888:
   286 			{
   287 			color = aColor.Color16MU();
   288 			break;
   289 			}
   290 		case EUidPixelFormatARGB_8888:
   291 			{
   292 			color = aColor.Color16MA();
   293 			break;
   294 			}
   295 		case EUidPixelFormatARGB_8888_PRE:
   296 			{
   297 			color = aColor.Color16MAP();
   298 			break;
   299 			}
   300 		case EUidPixelFormatXRGB_4444:
   301 		case EUidPixelFormatARGB_4444:
   302 			{
   303 			color = aColor.Color4K();
   304 			use16 = ETrue;
   305 			break;
   306 			}
   307 		case EUidPixelFormatRGB_565:
   308 			{
   309 			color = aColor.Color64K();
   310 			use16 = ETrue;
   311 			break;
   312 			}
   313 		default:
   314 			{
   315 			User::Leave(KErrNotSupported);
   316 			break;
   317 			}
   318 		}
   319 
   320     SymbianStreamBuffer bufferHandle;
   321     User::LeaveIfError(SymbianStreamAcquireWriteBuffer(aStream, &bufferHandle));
   322     long bufferIndex;
   323     const TSurfaceId* surfaceId = NULL;
   324     User::LeaveIfError(SymbianStreamGetBufferId(aStream,bufferHandle,&bufferIndex,&surfaceId));
   325 
   326 	RChunk chunk;
   327 	User::LeaveIfError(iManager.MapSurface(*surfaceId, chunk));
   328 	CleanupClosePushL(chunk);
   329 
   330 	TInt offsetToFirstBuffer;
   331 	User::LeaveIfError(iManager.GetBufferOffset(*surfaceId, 0, offsetToFirstBuffer));
   332 	TUint8* streamPtr = chunk.Base() + offsetToFirstBuffer;
   333 	TUint8* linePtr = streamPtr;
   334 
   335 	if (use16)
   336 		{
   337 		if ( width*2>stride)
   338 			{
   339 			User::Leave(KErrOverflow);
   340 			}
   341 		TUint16* ptr = reinterpret_cast<TUint16*>(streamPtr);
   342 
   343 		// Fill first line
   344 		for (TInt xx = 0; xx < width; xx++)
   345 			{
   346 			ptr[xx] = (TUint16)color;
   347 			}
   348 		}
   349 	else
   350 		{
   351 		if ( width*4>stride)
   352 			{
   353 			User::Leave(KErrOverflow);
   354 			}
   355 		TUint32* ptr = reinterpret_cast<TUint32*>(streamPtr);
   356 
   357 		// Fill first line
   358 		for (TInt xx = 0; xx < width; xx++)
   359 			{
   360 			ptr[xx] = color;
   361 			}
   362 		}
   363 
   364 	// Now copy that to the other lines
   365 	for (TInt yy = 1; yy < height; yy++)
   366 		{
   367 		linePtr += stride;
   368 		Mem::Copy(linePtr, streamPtr, width * BytesPerPixelL(aStream));
   369 		}
   370 	User::LeaveIfError(SymbianStreamReleaseWriteBuffer(aStream, bufferHandle));
   371 	CleanupStack::PopAndDestroy(/* chunk */);
   372 	}
   373 
   374 /**
   375 Destroy a stream.
   376 
   377 As well as destroying the stream, it is removed from the set held for
   378 destruction during tear down.
   379 
   380 @param aStream	The stream to be destroyed.
   381 */
   382 void CStreamUtility::DestroyStream(SymbianStreamType aStream)
   383 	{
   384 	TInt index = iStreams.Find(aStream);
   385 	
   386 	if (index != KErrNotFound)
   387 		{
   388 		iStreams.Remove(index);
   389 		}
   390 
   391 	SymbianStreamRemoveReference(aStream);
   392 	}
   393 
   394 /**
   395 A helper function that returns the bytes per pixel for a given pixel format uid
   396 
   397 @param      aPixelFormat Pixel format UID to convert
   398 @return     The bytes per pixel
   399 */
   400 TInt CStreamUtility::BytesPerPixelL(TUidPixelFormat aPixelFormat)
   401     {
   402     TInt bytesPerPixel = 0;
   403     switch (aPixelFormat)
   404         {
   405         case EUidPixelFormatXRGB_8888:
   406         case EUidPixelFormatARGB_8888:
   407         case EUidPixelFormatARGB_8888_PRE:
   408             {
   409             bytesPerPixel = 4;
   410             break;
   411             }
   412         case EUidPixelFormatXRGB_4444:
   413         case EUidPixelFormatARGB_4444:
   414         case EUidPixelFormatRGB_565:
   415             {
   416             bytesPerPixel = 2;
   417             break;
   418             }
   419         default:
   420             {
   421             User::Leave(KErrNotSupported);
   422             break;
   423             }
   424         }
   425     return bytesPerPixel;
   426     }
   427 
   428 /**
   429 A helper function that returns the bytes per pixel for a given stream
   430 
   431 @param      aStream The stream which is checked
   432 @return     The bytes per pixel
   433 */
   434 TInt CStreamUtility::BytesPerPixelL(const SymbianStreamType aStream)
   435     {
   436     khronos_int32_t width;
   437     khronos_int32_t height;
   438     khronos_int32_t stride;
   439     khronos_int32_t format;
   440     khronos_int32_t pixelSize;
   441         
   442     SymbianStreamGetHeader(aStream, &width, &height, &stride, &format, &pixelSize);
   443 
   444     return static_cast<TInt>(pixelSize);
   445     }
   446