graphicscomposition/openwfcompositionengine/test/tscreeninterface/streamutility.cpp
branchRCL_3
changeset 163 bbf46f59e123
equal deleted inserted replaced
150:57c618273d5c 163:bbf46f59e123
       
     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