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