os/graphics/graphicscomposition/openwfcompositionengine/test/tscreeninterface/streamutility.cpp
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 +