os/graphics/graphicscomposition/openwfcompositionengine/test/tscreeninterface/streamutility.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicscomposition/openwfcompositionengine/test/tscreeninterface/streamutility.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,446 @@
     1.4 +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +//
     1.6 +// Permission is hereby granted, free of charge, to any person obtaining a
     1.7 +// copy of this software and/or associated documentation files (the
     1.8 +// "Materials"), to deal in the Materials without restriction, including
     1.9 +// without limitation the rights to use, copy, modify, merge, publish,
    1.10 +// distribute, sublicense, and/or sell copies of the Materials, and to
    1.11 +// permit persons to whom the Materials are furnished to do so, subject to
    1.12 +// the following conditions:
    1.13 +//
    1.14 +// The above copyright notice and this permission notice shall be included
    1.15 +// in all copies or substantial portions of the Materials.
    1.16 +//
    1.17 +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1.18 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1.19 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    1.20 +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    1.21 +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    1.22 +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    1.23 +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    1.24 +//
    1.25 +// Description:
    1.26 +//
    1.27 +
    1.28 +/**
    1.29 + @file
    1.30 +*/
    1.31 +
    1.32 +#include <e32std.h>
    1.33 +#include <imageconversion.h>
    1.34 +#include <graphics/symbianstream.h>
    1.35 +#include "streamutility.h"
    1.36 +
    1.37 +#define WFC_INVALID_HANDLE NULL
    1.38 +
    1.39 +CStreamUtility::CStreamUtility()
    1.40 +	{
    1.41 +	}
    1.42 +	
    1.43 +CStreamUtility* CStreamUtility::NewL()
    1.44 +	{
    1.45 +	CStreamUtility* utility = new (ELeave)CStreamUtility();
    1.46 +	CleanupStack::PushL(utility);
    1.47 +	utility->ConstructL();
    1.48 +	CleanupStack::Pop(utility);
    1.49 +	return utility;
    1.50 +	}
    1.51 +	
    1.52 +void CStreamUtility::ConstructL()
    1.53 +	{
    1.54 +	TInt r = iManager.Open();
    1.55 +	if (r != KErrNone)
    1.56 +		{
    1.57 +		LOG(("Surface manager failed to open: %d", r));
    1.58 +		User::Leave(r);
    1.59 +		}
    1.60 +	}
    1.61 +	
    1.62 +CStreamUtility::~CStreamUtility()
    1.63 +	{
    1.64 +	DestroyAll();
    1.65 +
    1.66 +	iStreams.Close();
    1.67 +
    1.68 +	iManager.Close();
    1.69 +	}
    1.70 +
    1.71 +TBool CStreamUtility::DestroyAll()
    1.72 +	{
    1.73 +	TInt err = 	KErrNone;
    1.74 +	TInt jj = iStreams.Count() - 1;
    1.75 +	if (jj<0)
    1.76 +		return EFalse;
    1.77 +	for (; jj >= 0; jj--)
    1.78 +		{
    1.79 +        //The following lines are just to get the surface ID for verification
    1.80 +		SymbianStreamBuffer bufferHandle;
    1.81 +		User::LeaveIfError(SymbianStreamAcquireReadBuffer(iStreams[jj], &bufferHandle));
    1.82 +		long bufferIndex;
    1.83 +		const TSurfaceId* pSurfaceId = NULL;
    1.84 +		
    1.85 +		User::LeaveIfError(SymbianStreamGetBufferId(iStreams[jj],bufferHandle,&bufferIndex,&pSurfaceId));
    1.86 +        User::LeaveIfError(SymbianStreamReleaseReadBuffer(iStreams[jj], bufferHandle));
    1.87 +        
    1.88 +        const TSurfaceId surfaceId = *pSurfaceId;   //Need to copy my reference to the ID.
    1.89 +        //Actually release the stream
    1.90 +        SymbianStreamRemoveReference(iStreams[jj]);
    1.91 +        
    1.92 +        //Verify the stream is now not accessible
    1.93 +        TInt offset;
    1.94 +		err = iManager.GetBufferOffset(surfaceId,0,offset);
    1.95 +		if (err==KErrNone)
    1.96 +			{
    1.97 +			LOG(("Closing stream via DestoryAll did not destroy surface!"));
    1.98 +			}
    1.99 +		}
   1.100 +	iStreams.Reset();
   1.101 +	return ETrue;
   1.102 +	}
   1.103 +
   1.104 +/***************************************
   1.105 + * The aim of the RHeapStreamArray is to locally switch in the specified heap for any array operation
   1.106 + ***************************************/
   1.107 +
   1.108 +CStreamUtility::RHeapStreamArray::RHeapStreamArray(RHeapStreamArray* aUseExternalArray)
   1.109 +	:	iUseArray(aUseExternalArray?aUseExternalArray->iUseArray:&this->iLocalArray),
   1.110 +	iExternalHeapRef(aUseExternalArray?aUseExternalArray->iExternalHeapRef:User::Heap())
   1.111 +	{
   1.112 +	
   1.113 +	}
   1.114 +/************************************
   1.115 + * The following methods have been used by the streamutility... some require the heap wrapping, and some don't
   1.116 + * I actually need three different strategies (count em) for 7 methods...
   1.117 + * Some methods only read the existing objects, so don't need a heap swap at all
   1.118 + * Leaving methods have to use PopAndDestroy strategy to restore the heap on leaving or success
   1.119 + * Non-leaving methods must not call PushL, so directly make SwitchHeap calls!
   1.120 + ************************************/
   1.121 +
   1.122 +/// PopAndDestroy method to restore the heap
   1.123 +/*static*/ void	CStreamUtility::RHeapStreamArray::PopHeap(void* aHeapPtr)
   1.124 +	{
   1.125 +	RHeap* heapPtr=(RHeap*)aHeapPtr;
   1.126 +	User::SwitchHeap(heapPtr);
   1.127 +	}
   1.128 +
   1.129 +SymbianStreamType& CStreamUtility::RHeapStreamArray::operator[](TUint aIndex)
   1.130 +	{
   1.131 +	return iUseArray->operator[](aIndex);
   1.132 +	}
   1.133 +
   1.134 +/// Close only closes the local array, while Reset resets the active array (may be external)
   1.135 +void CStreamUtility::RHeapStreamArray::Close()
   1.136 +	{
   1.137 +	iLocalArray.Close();
   1.138 +	}
   1.139 +
   1.140 +TInt CStreamUtility::RHeapStreamArray::Count() const
   1.141 +	{
   1.142 +	return iUseArray->Count();
   1.143 +	}
   1.144 +
   1.145 +/// Close only closes the local array, while Reset resets the active array (may be external)
   1.146 +inline void CStreamUtility::RHeapStreamArray::Reset()
   1.147 +	{
   1.148 +	iUseArray->Reset();
   1.149 +	}
   1.150 +
   1.151 +void CStreamUtility::RHeapStreamArray::AppendL(const SymbianStreamType &anEntry)
   1.152 +	{
   1.153 +	iUseArray->AppendL(anEntry);
   1.154 +	}
   1.155 +
   1.156 +TInt CStreamUtility::RHeapStreamArray::Find(const SymbianStreamType &anEntry) const
   1.157 +	{
   1.158 +	return iUseArray->Find(anEntry);
   1.159 +	}
   1.160 +
   1.161 +void CStreamUtility::RHeapStreamArray::Remove(TInt anIndex)
   1.162 +	{
   1.163 +	iUseArray->Remove(anIndex);
   1.164 +	}
   1.165 +
   1.166 +/**
   1.167 +Cleanup stack helper object, holding references to both utility and stream, so
   1.168 +that the standard Close() semantics can be used.
   1.169 +*/
   1.170 +class TStreamCleanup
   1.171 +	{
   1.172 +public:
   1.173 +	TStreamCleanup(CStreamUtility& aUtility, SymbianStreamType& aStream)
   1.174 +		: iUtility(aUtility), iStream(aStream)
   1.175 +		{}
   1.176 +	void Close()
   1.177 +		{
   1.178 +		// Removes the stream from the list of streams to clean up, and closes
   1.179 +		// the stream reference.
   1.180 +		iUtility.DestroyStream(iStream);
   1.181 +		}
   1.182 +private:
   1.183 +	CStreamUtility& iUtility;
   1.184 +	SymbianStreamType& iStream;
   1.185 +	};
   1.186 +
   1.187 +/**
   1.188 +Get the size of a stream.
   1.189 +
   1.190 +@param  aStream The stream to get the size for.
   1.191 +@return The size in pixels, or empty on failure.
   1.192 +*/
   1.193 +TSize CStreamUtility::StreamSize(const SymbianStreamType aStream)
   1.194 +	{
   1.195 +	khronos_int32_t width;
   1.196 +	khronos_int32_t height;
   1.197 +	khronos_int32_t stride;
   1.198 +	khronos_int32_t format;
   1.199 +	khronos_int32_t pixelSize;
   1.200 +		
   1.201 +	SymbianStreamGetHeader(aStream, &width, &height, &stride, &format, &pixelSize);
   1.202 +	
   1.203 +	TSize size = TSize(static_cast<TInt>(width), static_cast<TInt>(height));
   1.204 +	
   1.205 +	return size;
   1.206 +	}
   1.207 +
   1.208 +/**
   1.209 +Create a stream using the surface manager.
   1.210 +
   1.211 +Stores the ID for tear down, as well as returning it.
   1.212 +
   1.213 +@param aSize            Dimensions of the stream.
   1.214 +@param aPixelFormat	    UID of the pixel format.
   1.215 +@param aStride	        Stride value for the stream (usually bytes per pixel * width)
   1.216 +@param aReturnSurface   Returns TSurfaceId wrapped by the stream
   1.217 +@param aContiguous      Contiguous flag for creating surfaces
   1.218 +@param aBuffers         Number of buffers
   1.219 +@leave May leave due to lack of memory.
   1.220 +@return New stream's ID.
   1.221 +*/
   1.222 +SymbianStreamType CStreamUtility::CreateStreamL(const TSize& aSize, TUidPixelFormat aPixelFormat, 
   1.223 +                                            TInt aStride, TSurfaceId& aReturnSurface, 
   1.224 +                                            TBool aContiguous, TInt aBuffers)
   1.225 +	{
   1.226 +	RSurfaceManager::TSurfaceCreationAttributesBuf bf;
   1.227 +	RSurfaceManager::TSurfaceCreationAttributes& b = bf();
   1.228 +	if (aStride<aSize.iWidth*BytesPerPixelL(aPixelFormat))
   1.229 +	    {
   1.230 +	    User::Leave(KErrOverflow);
   1.231 +	    }
   1.232 +	b.iSize.iWidth = aSize.iWidth;
   1.233 +	b.iSize.iHeight = aSize.iHeight;
   1.234 +	b.iBuffers = aBuffers;				// number of buffers in the surface
   1.235 +	b.iPixelFormat = aPixelFormat;
   1.236 +	b.iStride = aStride;		// Number of bytes between start of one line and start of next
   1.237 +	b.iOffsetToFirstBuffer = 0;	// way of reserving space before the surface pixel data
   1.238 +	b.iAlignment = 4;			// alignment, 1,2,4,8 byte aligned
   1.239 +	b.iContiguous = !!aContiguous;
   1.240 +	b.iMappable = ETrue;
   1.241 +
   1.242 +	aReturnSurface = TSurfaceId::CreateNullId();
   1.243 +
   1.244 +	User::LeaveIfError(iManager.CreateSurface(bf, aReturnSurface));
   1.245 +	
   1.246 +	SymbianStreamType ns;
   1.247 +	TInt err = SymbianStreamAcquire(&aReturnSurface, &ns);
   1.248 +    iManager.CloseSurface(aReturnSurface);		//The stream should now own the only reference
   1.249 +	if (err != KErrNone)
   1.250 +		{
   1.251 +		User::Leave(err);	
   1.252 +		}
   1.253 +	iStreams.AppendL(ns);
   1.254 +	return ns;
   1.255 +	}
   1.256 +
   1.257 +/**
   1.258 +Fill the given stream with a color.
   1.259 +
   1.260 +@param aStream	The stream to be filled.
   1.261 +@param aColor	The color to fill it with.
   1.262 +*/
   1.263 +void CStreamUtility::FillStreamL(SymbianStreamType aStream, const TRgb& aColor)
   1.264 +	{
   1.265 +	
   1.266 +	khronos_int32_t width;
   1.267 +	khronos_int32_t height;
   1.268 +	khronos_int32_t stride;
   1.269 +	khronos_int32_t format;
   1.270 +	khronos_int32_t pixelSize;
   1.271 +		
   1.272 +	SymbianStreamGetHeader(aStream, &width, &height, &stride, &format, &pixelSize);
   1.273 +
   1.274 +	TUint32 color = 0;
   1.275 +	TBool use16 = EFalse;
   1.276 +
   1.277 +	if (height<0 || width<0 || stride<0)
   1.278 +		{
   1.279 +		User::Leave(KErrCorrupt);
   1.280 +		}
   1.281 +	if (height==0 || width==0 || stride==0)
   1.282 +		{
   1.283 +		User::Leave(KErrNotReady);
   1.284 +		}
   1.285 +
   1.286 +	switch (format)
   1.287 +		{
   1.288 +		case EUidPixelFormatXRGB_8888:
   1.289 +			{
   1.290 +			color = aColor.Color16MU();
   1.291 +			break;
   1.292 +			}
   1.293 +		case EUidPixelFormatARGB_8888:
   1.294 +			{
   1.295 +			color = aColor.Color16MA();
   1.296 +			break;
   1.297 +			}
   1.298 +		case EUidPixelFormatARGB_8888_PRE:
   1.299 +			{
   1.300 +			color = aColor.Color16MAP();
   1.301 +			break;
   1.302 +			}
   1.303 +		case EUidPixelFormatXRGB_4444:
   1.304 +		case EUidPixelFormatARGB_4444:
   1.305 +			{
   1.306 +			color = aColor.Color4K();
   1.307 +			use16 = ETrue;
   1.308 +			break;
   1.309 +			}
   1.310 +		case EUidPixelFormatRGB_565:
   1.311 +			{
   1.312 +			color = aColor.Color64K();
   1.313 +			use16 = ETrue;
   1.314 +			break;
   1.315 +			}
   1.316 +		default:
   1.317 +			{
   1.318 +			User::Leave(KErrNotSupported);
   1.319 +			break;
   1.320 +			}
   1.321 +		}
   1.322 +
   1.323 +    SymbianStreamBuffer bufferHandle;
   1.324 +    User::LeaveIfError(SymbianStreamAcquireWriteBuffer(aStream, &bufferHandle));
   1.325 +    long bufferIndex;
   1.326 +    const TSurfaceId* surfaceId = NULL;
   1.327 +    User::LeaveIfError(SymbianStreamGetBufferId(aStream,bufferHandle,&bufferIndex,&surfaceId));
   1.328 +
   1.329 +	RChunk chunk;
   1.330 +	User::LeaveIfError(iManager.MapSurface(*surfaceId, chunk));
   1.331 +	CleanupClosePushL(chunk);
   1.332 +
   1.333 +	TInt offsetToFirstBuffer;
   1.334 +	User::LeaveIfError(iManager.GetBufferOffset(*surfaceId, 0, offsetToFirstBuffer));
   1.335 +	TUint8* streamPtr = chunk.Base() + offsetToFirstBuffer;
   1.336 +	TUint8* linePtr = streamPtr;
   1.337 +
   1.338 +	if (use16)
   1.339 +		{
   1.340 +		if ( width*2>stride)
   1.341 +			{
   1.342 +			User::Leave(KErrOverflow);
   1.343 +			}
   1.344 +		TUint16* ptr = reinterpret_cast<TUint16*>(streamPtr);
   1.345 +
   1.346 +		// Fill first line
   1.347 +		for (TInt xx = 0; xx < width; xx++)
   1.348 +			{
   1.349 +			ptr[xx] = (TUint16)color;
   1.350 +			}
   1.351 +		}
   1.352 +	else
   1.353 +		{
   1.354 +		if ( width*4>stride)
   1.355 +			{
   1.356 +			User::Leave(KErrOverflow);
   1.357 +			}
   1.358 +		TUint32* ptr = reinterpret_cast<TUint32*>(streamPtr);
   1.359 +
   1.360 +		// Fill first line
   1.361 +		for (TInt xx = 0; xx < width; xx++)
   1.362 +			{
   1.363 +			ptr[xx] = color;
   1.364 +			}
   1.365 +		}
   1.366 +
   1.367 +	// Now copy that to the other lines
   1.368 +	for (TInt yy = 1; yy < height; yy++)
   1.369 +		{
   1.370 +		linePtr += stride;
   1.371 +		Mem::Copy(linePtr, streamPtr, width * BytesPerPixelL(aStream));
   1.372 +		}
   1.373 +	User::LeaveIfError(SymbianStreamReleaseWriteBuffer(aStream, bufferHandle));
   1.374 +	CleanupStack::PopAndDestroy(/* chunk */);
   1.375 +	}
   1.376 +
   1.377 +/**
   1.378 +Destroy a stream.
   1.379 +
   1.380 +As well as destroying the stream, it is removed from the set held for
   1.381 +destruction during tear down.
   1.382 +
   1.383 +@param aStream	The stream to be destroyed.
   1.384 +*/
   1.385 +void CStreamUtility::DestroyStream(SymbianStreamType aStream)
   1.386 +	{
   1.387 +	TInt index = iStreams.Find(aStream);
   1.388 +	
   1.389 +	if (index != KErrNotFound)
   1.390 +		{
   1.391 +		iStreams.Remove(index);
   1.392 +		}
   1.393 +
   1.394 +	SymbianStreamRemoveReference(aStream);
   1.395 +	}
   1.396 +
   1.397 +/**
   1.398 +A helper function that returns the bytes per pixel for a given pixel format uid
   1.399 +
   1.400 +@param      aPixelFormat Pixel format UID to convert
   1.401 +@return     The bytes per pixel
   1.402 +*/
   1.403 +TInt CStreamUtility::BytesPerPixelL(TUidPixelFormat aPixelFormat)
   1.404 +    {
   1.405 +    TInt bytesPerPixel = 0;
   1.406 +    switch (aPixelFormat)
   1.407 +        {
   1.408 +        case EUidPixelFormatXRGB_8888:
   1.409 +        case EUidPixelFormatARGB_8888:
   1.410 +        case EUidPixelFormatARGB_8888_PRE:
   1.411 +            {
   1.412 +            bytesPerPixel = 4;
   1.413 +            break;
   1.414 +            }
   1.415 +        case EUidPixelFormatXRGB_4444:
   1.416 +        case EUidPixelFormatARGB_4444:
   1.417 +        case EUidPixelFormatRGB_565:
   1.418 +            {
   1.419 +            bytesPerPixel = 2;
   1.420 +            break;
   1.421 +            }
   1.422 +        default:
   1.423 +            {
   1.424 +            User::Leave(KErrNotSupported);
   1.425 +            break;
   1.426 +            }
   1.427 +        }
   1.428 +    return bytesPerPixel;
   1.429 +    }
   1.430 +
   1.431 +/**
   1.432 +A helper function that returns the bytes per pixel for a given stream
   1.433 +
   1.434 +@param      aStream The stream which is checked
   1.435 +@return     The bytes per pixel
   1.436 +*/
   1.437 +TInt CStreamUtility::BytesPerPixelL(const SymbianStreamType aStream)
   1.438 +    {
   1.439 +    khronos_int32_t width;
   1.440 +    khronos_int32_t height;
   1.441 +    khronos_int32_t stride;
   1.442 +    khronos_int32_t format;
   1.443 +    khronos_int32_t pixelSize;
   1.444 +        
   1.445 +    SymbianStreamGetHeader(aStream, &width, &height, &stride, &format, &pixelSize);
   1.446 +
   1.447 +    return static_cast<TInt>(pixelSize);
   1.448 +    }
   1.449 +