os/graphics/graphicscomposition/openwfsupport/src/surfacestream.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// SurfaceStream.cpp
sl@0
    15
// CSurfaceStream implementation
sl@0
    16
sl@0
    17
#include <e32base.h>
sl@0
    18
#include <graphics/suerror.h>
sl@0
    19
#include <graphics/surfacetypes.h>
sl@0
    20
#include <hal.h>
sl@0
    21
#include "surfacestream.h"
sl@0
    22
#include "openwfcpanic.h"
sl@0
    23
#include "streammap.h"
sl@0
    24
#include "symbianstream.h"
sl@0
    25
#define WFC_INVALID_HANDLE NULL
sl@0
    26
sl@0
    27
const TInt KInvalidIndex = KNoAssociatedScreenNumber;
sl@0
    28
sl@0
    29
struct CSurfaceStream::TCallBackEntry
sl@0
    30
	{
sl@0
    31
	typedef SymbianStreamCallback	TSimpleCallback;
sl@0
    32
	TCallBackEntry();
sl@0
    33
	void Reset();
sl@0
    34
	TSimpleCallback iCallBackFunction;
sl@0
    35
	TAny*			iCallBackClientParam;
sl@0
    36
	TInt32			iEventMask;
sl@0
    37
	TInt32          iScreenNumber;
sl@0
    38
	};
sl@0
    39
sl@0
    40
CSurfaceStream::TCallBackEntry::TCallBackEntry():
sl@0
    41
iCallBackFunction(NULL),
sl@0
    42
iCallBackClientParam(NULL),
sl@0
    43
iEventMask(ESOWF_NoEvent),
sl@0
    44
iScreenNumber(KNoAssociatedScreenNumber)
sl@0
    45
    {
sl@0
    46
    }
sl@0
    47
sl@0
    48
void CSurfaceStream::TCallBackEntry::Reset()
sl@0
    49
    {
sl@0
    50
    iCallBackFunction = NULL;
sl@0
    51
    iCallBackClientParam = NULL;
sl@0
    52
    iEventMask = ESOWF_NoEvent;
sl@0
    53
    iScreenNumber = KNoAssociatedScreenNumber;
sl@0
    54
    }
sl@0
    55
sl@0
    56
struct CSurfaceStream::TGlobalNotification
sl@0
    57
    {
sl@0
    58
    TGlobalNotification();
sl@0
    59
    void Reset();
sl@0
    60
    TRequestStatus* iStatus;
sl@0
    61
    TThreadId       iThreadId;
sl@0
    62
    TInt            iPendingNotifications;
sl@0
    63
    TInt            iCompletedOkNotifications;
sl@0
    64
    TInt            iCanceledNotifications;
sl@0
    65
    TInt            iOverflowedNotifications;
sl@0
    66
    TInt            iNotVisibleNotifications;
sl@0
    67
    TInt            iOtherNotifications;
sl@0
    68
    };
sl@0
    69
sl@0
    70
sl@0
    71
CSurfaceStream::TGlobalNotification::TGlobalNotification():
sl@0
    72
iStatus(NULL),
sl@0
    73
iThreadId(0),
sl@0
    74
iPendingNotifications(0),
sl@0
    75
iCompletedOkNotifications(0),
sl@0
    76
iCanceledNotifications(0),
sl@0
    77
iOverflowedNotifications(0),
sl@0
    78
iNotVisibleNotifications(0),
sl@0
    79
iOtherNotifications(0)
sl@0
    80
    {
sl@0
    81
    
sl@0
    82
    }
sl@0
    83
sl@0
    84
void CSurfaceStream::TGlobalNotification::Reset()
sl@0
    85
    {
sl@0
    86
    iStatus = NULL;
sl@0
    87
    iThreadId = 0;
sl@0
    88
    iPendingNotifications = 0;
sl@0
    89
    iCompletedOkNotifications = 0;
sl@0
    90
    iCanceledNotifications = 0;
sl@0
    91
    iOverflowedNotifications = 0;
sl@0
    92
    iNotVisibleNotifications = 0;
sl@0
    93
    iOtherNotifications = 0;
sl@0
    94
    }
sl@0
    95
sl@0
    96
struct CSurfaceStream::TNewGlobalNotifications
sl@0
    97
    {
sl@0
    98
    TNewGlobalNotifications();
sl@0
    99
    TInt iNewAvailableIdx;
sl@0
   100
    TInt iNewDisplayedIdx;
sl@0
   101
    TInt iNewDisplayedXIdx;
sl@0
   102
    };
sl@0
   103
sl@0
   104
CSurfaceStream::TNewGlobalNotifications::TNewGlobalNotifications():
sl@0
   105
iNewAvailableIdx(KInvalidIndex),
sl@0
   106
iNewDisplayedIdx(KInvalidIndex),
sl@0
   107
iNewDisplayedXIdx(KInvalidIndex)
sl@0
   108
    {
sl@0
   109
    }
sl@0
   110
sl@0
   111
CSurfaceStream::Guard::Guard(RFastLock& aLock):
sl@0
   112
iLock(aLock)
sl@0
   113
    {
sl@0
   114
    iLock.Wait();
sl@0
   115
    }
sl@0
   116
sl@0
   117
CSurfaceStream::Guard::~Guard()
sl@0
   118
    {
sl@0
   119
    iLock.Signal();
sl@0
   120
    }
sl@0
   121
sl@0
   122
CSurfaceStream::CSurfaceStream():
sl@0
   123
	iSurfaceId(TSurfaceId::CreateNullId()),
sl@0
   124
	iBufferInfo(NULL),
sl@0
   125
	iProtected(EFalse),
sl@0
   126
	iNumberOfScreenAttachedAvailableNotif(0),
sl@0
   127
	iNumberOfScreenAttachedDisplayedNotif(0),
sl@0
   128
	iNumberOfScreenAttachedDisplayedXNotif(),
sl@0
   129
	iFlipState(EFlippedTargetNormal),
sl@0
   130
    iNewFlip(EFlipNotSet)
sl@0
   131
	{
sl@0
   132
	iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::EObjectRefField]=
sl@0
   133
			reinterpret_cast<TInt>(this);
sl@0
   134
	iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::ETypeClassField]=
sl@0
   135
			TSurfaceId::EStreamHandle<<TSurfaceId::TSurfaceUsage::ETypeClassShift;
sl@0
   136
	}
sl@0
   137
sl@0
   138
CSurfaceStream::ContentUpdatedParams::ContentUpdatedParams(TInt aBuffer,
sl@0
   139
                                                           TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
sl@0
   140
                                                           TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
sl@0
   141
                                                           TRequestStatus* aStatusConsumed, const TRegion* aRegion,
sl@0
   142
                                                           TBool aImmediateAvailable, TInt32 aImmediateVisibility,
sl@0
   143
                                                           const TNewGlobalNotifications& aGlobalNotifications):
sl@0
   144
iBuffer(aBuffer),
sl@0
   145
iStatusDisplayed(aStatusDisplayed),
sl@0
   146
iTimeStamp(aTimeStamp),
sl@0
   147
iStatusDispXTimes(aStatusDispXTimes),
sl@0
   148
iDisplayedXTimes(aDisplayedXTimes),
sl@0
   149
iStatusConsumed(aStatusConsumed),
sl@0
   150
iRegion(aRegion),
sl@0
   151
iImmediateAvailable(aImmediateAvailable),
sl@0
   152
iImmediateVisibility(aImmediateVisibility),
sl@0
   153
iGlobalNotifications(aGlobalNotifications)
sl@0
   154
    {
sl@0
   155
    
sl@0
   156
    }
sl@0
   157
sl@0
   158
CSurfaceStream::~CSurfaceStream()
sl@0
   159
	{
sl@0
   160
	// Cancel any outstanding notifications
sl@0
   161
	CancelNotifications();
sl@0
   162
    iCallBacks.Close();
sl@0
   163
    iGlobalNotifications.Close();
sl@0
   164
    iBufferChunk.Close();
sl@0
   165
	
sl@0
   166
    if (!iSurfaceId.IsNull() && iSurfaceId.Type() == TSurfaceTypes::ESurfaceManagerSurface)
sl@0
   167
        {
sl@0
   168
        TRAP_IGNORE(GetSingletonL().SurfaceManager().CloseSurface(iSurfaceId));
sl@0
   169
        }
sl@0
   170
	
sl@0
   171
	iRefCountMutex.Close();
sl@0
   172
	iCallBacksMutex.Close();
sl@0
   173
	delete [] iBufferInfo;
sl@0
   174
	}
sl@0
   175
sl@0
   176
CSurfaceStream* CSurfaceStream::NewLC(const TSurfaceId& aId)
sl@0
   177
	{
sl@0
   178
	CSurfaceStream* self = new (ELeave)CSurfaceStream();
sl@0
   179
	CleanupStack::PushL(self);
sl@0
   180
	self->ConstructL(aId);
sl@0
   181
	return self;
sl@0
   182
	}
sl@0
   183
sl@0
   184
void CSurfaceStream::ConstructL(const TSurfaceId& aId)
sl@0
   185
	{
sl@0
   186
	User::LeaveIfError(iRefCountMutex.CreateLocal());
sl@0
   187
    User::LeaveIfError(iCallBacksMutex.CreateLocal());
sl@0
   188
   
sl@0
   189
    RSurfaceManager::TInfoBuf infoBuf;  
sl@0
   190
    SurfaceInfoL(aId, infoBuf);
sl@0
   191
	iInfo = infoBuf();
sl@0
   192
sl@0
   193
    COpenWfcStreamMap& stream = GetSingletonL();
sl@0
   194
	//Create array for TBufferInfo
sl@0
   195
	iBufferInfo = new(ELeave) TBufferInfo[iInfo.iBuffers];
sl@0
   196
	for(TInt i = 0; i < iInfo.iBuffers; i++)
sl@0
   197
		{
sl@0
   198
		TInt offset = 0;
sl@0
   199
	    switch(aId.Type())
sl@0
   200
	        {
sl@0
   201
	        case TSurfaceTypes::ESurfaceManagerSurface:
sl@0
   202
	            {
sl@0
   203
	            User::LeaveIfError(stream.SurfaceManager().GetBufferOffset(iSurfaceId,
sl@0
   204
	                     i, offset));
sl@0
   205
	            break;
sl@0
   206
	            }
sl@0
   207
	        case TSurfaceId::EScreenSurface:
sl@0
   208
	            {
sl@0
   209
	            TInt screenId = SurfaceId().iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField];
sl@0
   210
	            User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayOffsetToFirstPixel, offset));
sl@0
   211
	            break;
sl@0
   212
	            }
sl@0
   213
	        default:
sl@0
   214
	            User::Leave(KErrNotSupported);
sl@0
   215
	        }
sl@0
   216
sl@0
   217
		iBufferInfo[i].iRefCount = 0;
sl@0
   218
		iBufferInfo[i].iOffset = offset;
sl@0
   219
		}
sl@0
   220
	}
sl@0
   221
sl@0
   222
void CSurfaceStream::SurfaceInfoL(const TSurfaceId& aId, RSurfaceManager::TInfoBuf& aInfoBuf)
sl@0
   223
    {
sl@0
   224
    COpenWfcStreamMap& stream = GetSingletonL();    
sl@0
   225
    switch(aId.Type())
sl@0
   226
        {
sl@0
   227
        case TSurfaceTypes::ESurfaceManagerSurface:
sl@0
   228
            {
sl@0
   229
            iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::EObjectRefField]=
sl@0
   230
                    reinterpret_cast<TInt>(this);
sl@0
   231
            iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::ETypeClassField]=
sl@0
   232
                    TSurfaceId::EStreamHandle<<TSurfaceId::TSurfaceUsage::ETypeClassShift;        
sl@0
   233
            
sl@0
   234
            User::LeaveIfError(stream.SurfaceManager().OpenSurface(aId));            
sl@0
   235
            iSurfaceId = aId;
sl@0
   236
            User::LeaveIfError(stream.SurfaceManager().SurfaceInfo(iSurfaceId, aInfoBuf));
sl@0
   237
            break;
sl@0
   238
            }
sl@0
   239
        case TSurfaceId::EScreenSurface:
sl@0
   240
            {
sl@0
   241
            // DSA surface only has one buffer
sl@0
   242
            aInfoBuf().iBuffers = 1;
sl@0
   243
            
sl@0
   244
            TInt screenId = aId.iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField];
sl@0
   245
            TInt width;
sl@0
   246
            User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayXPixels, width));
sl@0
   247
                        
sl@0
   248
            TInt height;
sl@0
   249
            User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayYPixels, height));
sl@0
   250
            
sl@0
   251
            aInfoBuf().iSize = TSize(width, height);
sl@0
   252
            
sl@0
   253
            TInt bpp = 0;
sl@0
   254
            User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayBitsPerPixel, bpp));
sl@0
   255
sl@0
   256
            TUidPixelFormat pixelFormat = static_cast<TUidPixelFormat> (aId.iInternal[TSurfaceId::TScreenSurfaceUsage::ETypeGuidField]);
sl@0
   257
            if (!pixelFormat)
sl@0
   258
                {
sl@0
   259
                //if (bpp==12 || bpp==4))   //This allows low-color indices to be semi-functionally tested
sl@0
   260
                if (bpp==12)
sl@0
   261
                    {
sl@0
   262
                    pixelFormat = EUidPixelFormatXRGB_4444;
sl@0
   263
                    }
sl@0
   264
                else if (bpp == 16)
sl@0
   265
                    {
sl@0
   266
                    pixelFormat = EUidPixelFormatRGB_565;
sl@0
   267
                    }
sl@0
   268
                else if (bpp== 24 || bpp==32)
sl@0
   269
                    {
sl@0
   270
                    pixelFormat = EUidPixelFormatARGB_8888;
sl@0
   271
                    }
sl@0
   272
                else
sl@0
   273
                    {
sl@0
   274
                    User::Leave(KErrNotSupported);
sl@0
   275
                    }
sl@0
   276
sl@0
   277
                }
sl@0
   278
            aInfoBuf().iPixelFormat = pixelFormat;
sl@0
   279
            
sl@0
   280
#ifdef  SYMBIAN_ROTATION_MODE_CHANGES
sl@0
   281
            TInt displayMode = aId.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
sl@0
   282
#else
sl@0
   283
            TInt displayMode = 0;
sl@0
   284
            User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayMode, displayMode));
sl@0
   285
#endif            
sl@0
   286
            
sl@0
   287
#if defined(SYMBIAN_ROTATION_MODE_CHANGES)
sl@0
   288
            if (displayMode & TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag) // 90 | 270 degree rotation
sl@0
   289
                {
sl@0
   290
                // Swap dimensions and recalculate stride. Assume no padding for now.
sl@0
   291
                aInfoBuf().iSize.iWidth = height;
sl@0
   292
                aInfoBuf().iSize.iHeight = width;
sl@0
   293
                //"vertical" stride has already been fetched
sl@0
   294
                }
sl@0
   295
#elif defined(SYMBIAN_ROTATION_CHANGES)
sl@0
   296
            if (aSurface.iInternal[1] & (2 | 8))    // 90 | 270 degree rotation
sl@0
   297
                {
sl@0
   298
                // Swap dimensions and recalculate stride. Assume no padding for now.
sl@0
   299
                aInfoBuf().iSize.iWidth = height;
sl@0
   300
                aInfoBuf().iSize.iHeight = width;
sl@0
   301
                aInfoBuf().iStride = infoBuf().iSize.width * bpp;
sl@0
   302
                }
sl@0
   303
#endif            
sl@0
   304
            
sl@0
   305
            TInt stride = displayMode;
sl@0
   306
            User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayOffsetBetweenLines, stride));
sl@0
   307
sl@0
   308
            aInfoBuf().iStride = stride;             
sl@0
   309
            
sl@0
   310
            iSurfaceId = aId;
sl@0
   311
            break;
sl@0
   312
            }
sl@0
   313
        default:
sl@0
   314
            User::Leave(KErrNotSupported);
sl@0
   315
        } 
sl@0
   316
    }
sl@0
   317
sl@0
   318
COpenWfcStreamMap& CSurfaceStream::GetSingletonL()
sl@0
   319
	{
sl@0
   320
	return COpenWfcStreamMap::InstanceL();
sl@0
   321
	}
sl@0
   322
sl@0
   323
/**
sl@0
   324
	Helper to resolve handle to stream object
sl@0
   325
**/
sl@0
   326
/*static*/
sl@0
   327
CSurfaceStream* CSurfaceStream::FromHandle(SymbianStreamType aNativeStreamHandle)
sl@0
   328
	{
sl@0
   329
	if (aNativeStreamHandle)
sl@0
   330
		{
sl@0
   331
		if (aNativeStreamHandle->Type()==TSurfaceId::EStreamHandle)
sl@0
   332
			{
sl@0
   333
			return reinterpret_cast<CSurfaceStream*>(aNativeStreamHandle->iInternal[TSurfaceId::TSurfaceUsage::EObjectRefField]);
sl@0
   334
			}
sl@0
   335
		}
sl@0
   336
	return NULL;
sl@0
   337
	}
sl@0
   338
sl@0
   339
/**
sl@0
   340
	Helper to resolve handle to stream object
sl@0
   341
**/
sl@0
   342
SymbianStreamType CSurfaceStream::ToHandle()
sl@0
   343
	{
sl@0
   344
	if (this)
sl@0
   345
		{
sl@0
   346
		return &iStreamProxySurfaceId;
sl@0
   347
		}
sl@0
   348
	else
sl@0
   349
		{
sl@0
   350
		return NULL;
sl@0
   351
		}
sl@0
   352
	}
sl@0
   353
sl@0
   354
sl@0
   355
/**	Returns internal surface ID.
sl@0
   356
 *
sl@0
   357
 * @return surface id asociated with this stream
sl@0
   358
 **/
sl@0
   359
const TSurfaceId& CSurfaceStream::SurfaceId()const
sl@0
   360
	{
sl@0
   361
	return iSurfaceId;
sl@0
   362
	}
sl@0
   363
sl@0
   364
/*!
sl@0
   365
 * \brief Increase stream's reference count by one.
sl@0
   366
 *
sl@0
   367
 */
sl@0
   368
 void CSurfaceStream::AddReference()
sl@0
   369
	 {
sl@0
   370
	 iRefCountMutex.Wait();
sl@0
   371
	 iRefCount++;
sl@0
   372
	 iRefCountMutex.Signal();
sl@0
   373
sl@0
   374
	 }
sl@0
   375
sl@0
   376
/*!
sl@0
   377
 * \internal
sl@0
   378
 *
sl@0
   379
 * \brief Returns flag if reference count is now zero.
sl@0
   380
 *
sl@0
   381
 */
sl@0
   382
TBool	CSurfaceStream::RemainingReference()
sl@0
   383
	{
sl@0
   384
	 iRefCountMutex.Wait();
sl@0
   385
	 TBool countZero=iRefCount==0;
sl@0
   386
	 iRefCountMutex.Signal();
sl@0
   387
	 return countZero;
sl@0
   388
	}
sl@0
   389
sl@0
   390
sl@0
   391
/*!
sl@0
   392
 * \brief Decrease stream's reference count by one and destroy
sl@0
   393
 * the stream, if the reference count goes to zero.
sl@0
   394
 *
sl@0
   395
 * All acquired read & write buffers must be released
sl@0
   396
 * before calling WFC_Native_Destroy.
sl@0
   397
 *
sl@0
   398
 */
sl@0
   399
void CSurfaceStream::ReleaseReference()
sl@0
   400
	{
sl@0
   401
	iRefCountMutex.Wait();
sl@0
   402
	--iRefCount;
sl@0
   403
	if (iRefCount < 1)
sl@0
   404
		{
sl@0
   405
		// it is required to signal the mutex before calling LockDestroy()
sl@0
   406
		iRefCountMutex.Signal();
sl@0
   407
		TRAP_IGNORE(GetSingletonL().LockDestroy(this));
sl@0
   408
		}
sl@0
   409
	else
sl@0
   410
		{
sl@0
   411
		iRefCountMutex.Signal();
sl@0
   412
		}
sl@0
   413
	 }
sl@0
   414
sl@0
   415
/*!
sl@0
   416
 * \brief Get stream "frame header". Can be used to query
sl@0
   417
 * all or some of the frame properties.
sl@0
   418
 *
sl@0
   419
 * \param width Pointer to location where width parameter should be saved
sl@0
   420
 * \param height Pointer to location where height parameter should be saved
sl@0
   421
 * \param stride Pointer to location where stride (row size in bytes)
sl@0
   422
 * parameter should be saved
sl@0
   423
 * \param pixelSize Pointer to location where pizelSize (pixel size in bytes) if the format has more than 8 bits.
sl@0
   424
 *                  For the formats with fewer than 8 bits per pixel, or ones that do not use packed pixel 
sl@0
   425
 *                  the parameter is a negative number            
sl@0
   426
 * parameter should be saved
sl@0
   427
sl@0
   428
 * Passing a NULL pointer implies that particular
sl@0
   429
 * value is of no interest to caller. E.g.
sl@0
   430
 *   owfNativeStreamGetHeader(stream, &w, &h, NULL, NULL, NULL);
sl@0
   431
 * would only fetch width & height parameters.
sl@0
   432
 */
sl@0
   433
void CSurfaceStream::GetHeader(  khronos_int32_t* aWidth,
sl@0
   434
                           khronos_int32_t* aHeight,
sl@0
   435
                           khronos_int32_t* aStride,
sl@0
   436
                           SymOwfPixelFormat* aFormat,
sl@0
   437
                           khronos_int32_t* aPixelSize)
sl@0
   438
	 {
sl@0
   439
	 Guard g1(iRefCountMutex);
sl@0
   440
	 if (aWidth)
sl@0
   441
		 {
sl@0
   442
		 if (iFlipState == EFlippedTargetFlipped)
sl@0
   443
		     {
sl@0
   444
	         *aWidth = static_cast<khronos_int32_t>(iInfo.iSize.iHeight);
sl@0
   445
		     }
sl@0
   446
		 else
sl@0
   447
		     {
sl@0
   448
             *aWidth = static_cast<khronos_int32_t>(iInfo.iSize.iWidth);
sl@0
   449
		     }
sl@0
   450
		 }
sl@0
   451
	 
sl@0
   452
	 if (aHeight)
sl@0
   453
		 {
sl@0
   454
         if (iFlipState == EFlippedTargetFlipped)
sl@0
   455
             {
sl@0
   456
             *aHeight = static_cast<khronos_int32_t>(iInfo.iSize.iWidth);
sl@0
   457
             }
sl@0
   458
         else
sl@0
   459
             {
sl@0
   460
             *aHeight = static_cast<khronos_int32_t>(iInfo.iSize.iHeight);
sl@0
   461
             }
sl@0
   462
		 }
sl@0
   463
	 if (aStride)
sl@0
   464
		 {
sl@0
   465
         if (iFlipState == EFlippedTargetFlipped)
sl@0
   466
             {
sl@0
   467
             *aStride = Stride(iInfo.iSize.iHeight, iInfo.iPixelFormat);
sl@0
   468
             }
sl@0
   469
         else
sl@0
   470
             {
sl@0
   471
             *aStride = static_cast<khronos_int32_t>(iInfo.iStride);
sl@0
   472
             }
sl@0
   473
		 }
sl@0
   474
	 if (aFormat)
sl@0
   475
		 {
sl@0
   476
		 *aFormat=iInfo.iPixelFormat;
sl@0
   477
		 }
sl@0
   478
	 if (aPixelSize)
sl@0
   479
		 {
sl@0
   480
		*aPixelSize = static_cast<khronos_int32_t>(BytesPerPixel(iInfo.iPixelFormat));
sl@0
   481
		 }
sl@0
   482
	 }
sl@0
   483
sl@0
   484
/*!
sl@0
   485
 * \brief Acquires read buffer for stream. For > 1 buffer
sl@0
   486
 * streams this function doesn't block, but simply returns
sl@0
   487
 * WFC_INVALID_HANDLE if no buffer is available for reading.
sl@0
   488
 * For 1 buffer stream the caller is blocked until the buffer
sl@0
   489
 * is ready for reading (the reader has committed the buffer,
sl@0
   490
 * that is.)
sl@0
   491
 *
sl@0
   492
 *
sl@0
   493
 * \return WFC_INVALID_HANDLE if no buffer is available or
sl@0
   494
 * handle to last committed buffer.
sl@0
   495
 *
sl@0
   496
 * An example sequence for 3 buffer stream where
sl@0
   497
 * producer produces frames approx. after every ~5th time unit.
sl@0
   498
 * Consumer consumes buffers at constant rate of 1buf/time unit.
sl@0
   499
 * Pframe is the number/handle of buffer that is being written by
sl@0
   500
 * the producer (let's assume that it takes 2 time units
sl@0
   501
 * for producer to produce a frame/buffer.) Cframe is the number/
sl@0
   502
 * handle of the buffer the consumer receives from AcquireReadBuffer().
sl@0
   503
 * "i" stands for WFC_INVALID_HANDLE:
sl@0
   504
 *
sl@0
   505
 * \code
sl@0
   506
 * Time:   0    5    10   15   20   25
sl@0
   507
 * Pframe: 0    1    2    0    1    ...
sl@0
   508
 * Cframe: ii00000111112222200000111...
sl@0
   509
 * \endcode
sl@0
   510
 */
sl@0
   511
SymbianStreamBuffer CSurfaceStream::AcquireReadBuffer()
sl@0
   512
	 {
sl@0
   513
	 SymbianStreamBuffer buffer = WFC_INVALID_HANDLE;
sl@0
   514
sl@0
   515
	 iRefCountMutex.Wait();
sl@0
   516
	 TInt index = GetReadBufferIndex();
sl@0
   517
     buffer = IndexToReadHandle(index);
sl@0
   518
     ++(iBufferInfo[index].iRefCount);
sl@0
   519
	 iRefCountMutex.Signal();
sl@0
   520
	 AddReference();
sl@0
   521
	 return buffer;
sl@0
   522
	 }
sl@0
   523
sl@0
   524
/*!
sl@0
   525
 * \brief Releases read buffer.
sl@0
   526
 *
sl@0
   527
 * When read buffer is released, it is marked as clean to
sl@0
   528
 * be written again, unless it is the only committed buffer
sl@0
   529
 * in which case it is recycled so that the same buffer
sl@0
   530
 * can be read again (as long as no new buffers are committed
sl@0
   531
 * by the producer)
sl@0
   532
 *
sl@0
   533
 * \param buf Buffer handle. Must be valid read buffer handle for
sl@0
   534
 * given stream.
sl@0
   535
 */
sl@0
   536
TInt CSurfaceStream::ReleaseReadBuffer(SymbianStreamBuffer aBuf)
sl@0
   537
	 {
sl@0
   538
	 TInt index = BufferHandleToIndex(aBuf);
sl@0
   539
	 if(index < 0 || index >= iInfo.iBuffers)
sl@0
   540
		 {
sl@0
   541
		 return KErrBadHandle;
sl@0
   542
		 }
sl@0
   543
sl@0
   544
     iRefCountMutex.Wait();
sl@0
   545
sl@0
   546
      __ASSERT_DEBUG(iBufferInfo[index].iRefCount > 0, 
sl@0
   547
			 (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
sl@0
   548
sl@0
   549
      --(iBufferInfo[index].iRefCount);
sl@0
   550
     
sl@0
   551
     iRefCountMutex.Signal();
sl@0
   552
     ReleaseReference();
sl@0
   553
     return KErrNone;
sl@0
   554
	 }
sl@0
   555
sl@0
   556
/*!
sl@0
   557
 * \brief Acquires write buffer for stream.
sl@0
   558
 *
sl@0
   559
 * Returns handle to a buffer that can be used to write
sl@0
   560
 * data into stream. If no clean buffer is available,
sl@0
   561
 * invalid handle is returned.
sl@0
   562
 *
sl@0
   563
 *
sl@0
   564
 * \return Handle to a writable buffer
sl@0
   565
 */
sl@0
   566
SymbianStreamBuffer CSurfaceStream::AcquireWriteBuffer()
sl@0
   567
	 {
sl@0
   568
	 SymbianStreamBuffer   buffer = WFC_INVALID_HANDLE;
sl@0
   569
sl@0
   570
     iRefCountMutex.Wait();
sl@0
   571
     TInt index = GetWriteBufferIndex();
sl@0
   572
     //Writers are currently not blocked in single buffered,
sl@0
   573
     //but if proper signalling was implemented then they could be blocked
sl@0
   574
     //Ideally, make signalling/blocking a parameter flag of AcquireWriteBuffer
sl@0
   575
     if (iInfo.iBuffers>1 && iBufferInfo[index].iRefCount > 0)
sl@0
   576
       	{
sl@0
   577
        buffer = WFC_INVALID_HANDLE;
sl@0
   578
      	}
sl@0
   579
     else
sl@0
   580
       	{
sl@0
   581
        buffer = IndexToWriteHandle(index);
sl@0
   582
        ++(iBufferInfo[index].iRefCount);
sl@0
   583
        iAcquiredWriteBuffer = buffer;
sl@0
   584
       	}
sl@0
   585
    iRefCountMutex.Signal();
sl@0
   586
    if (buffer)
sl@0
   587
    	{
sl@0
   588
    	AddReference();
sl@0
   589
    	}
sl@0
   590
    return buffer;
sl@0
   591
	}
sl@0
   592
sl@0
   593
/*!
sl@0
   594
 * \brief Releases write buffer to stream.
sl@0
   595
 * Released buffer is made new front buffer, i.e., producer is expected
sl@0
   596
 * to release buffer is the same order they were acquired.
sl@0
   597
 *
sl@0
   598
 * \param buf Buffer handle. Must be valid write buffer handle
sl@0
   599
 * for given stream.
sl@0
   600
 */
sl@0
   601
void CSurfaceStream::ReleaseWriteBuffer(SymbianStreamBuffer aBuf)
sl@0
   602
	 {
sl@0
   603
	 TInt index = BufferHandleToIndex(aBuf);
sl@0
   604
	 if(index < 0 || index >= iInfo.iBuffers)
sl@0
   605
		 {
sl@0
   606
		 return;
sl@0
   607
		 }
sl@0
   608
sl@0
   609
	 iRefCountMutex.Wait();
sl@0
   610
sl@0
   611
     __ASSERT_DEBUG(iBufferInfo[index].iRefCount > 0,
sl@0
   612
			(iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
sl@0
   613
sl@0
   614
     __ASSERT_DEBUG((iAcquiredWriteBuffer == aBuf) || (iAcquiredWriteBuffer == BUFFER_WRITE_UPDATE_OVERWRITE),
sl@0
   615
			(iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
sl@0
   616
sl@0
   617
	 if (iAcquiredWriteBuffer != BUFFER_WRITE_UPDATE_OVERWRITE)
sl@0
   618
		 {
sl@0
   619
		 // Update read buffer to point to buffer just finished writing
sl@0
   620
		 SetReadBufferIndex(index);
sl@0
   621
		 }
sl@0
   622
	 iAcquiredWriteBuffer = WFC_INVALID_HANDLE;
sl@0
   623
sl@0
   624
     --(iBufferInfo[index].iRefCount);
sl@0
   625
	 
sl@0
   626
     if (iNewFlip != EFlipNotSet)
sl@0
   627
         {
sl@0
   628
         iFlipState = iNewFlip;
sl@0
   629
         iNewFlip = EFlipNotSet;
sl@0
   630
         }
sl@0
   631
     
sl@0
   632
	 iRefCountMutex.Signal();
sl@0
   633
sl@0
   634
	 NotifyObservers(ESOWF_EventComposed);
sl@0
   635
	 ReleaseReference();	//Note this means this NotifyObservers can never get the rug pulled out
sl@0
   636
	 }
sl@0
   637
sl@0
   638
sl@0
   639
void CSurfaceStream::SetReadBufferIndex(TInt aIndex)
sl@0
   640
	{
sl@0
   641
	__ASSERT_DEBUG(aIndex >= 0 && aIndex < iInfo.iBuffers,
sl@0
   642
			(iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferIndexOutOfBounds)));
sl@0
   643
	iReadBuffer = aIndex;
sl@0
   644
	}
sl@0
   645
sl@0
   646
TInt CSurfaceStream::GetReadBufferIndex()
sl@0
   647
	{
sl@0
   648
	return iReadBuffer;
sl@0
   649
	}
sl@0
   650
TInt CSurfaceStream::GetWriteBufferIndex()
sl@0
   651
	{
sl@0
   652
	return (iReadBuffer+1)%iInfo.iBuffers;
sl@0
   653
	}
sl@0
   654
sl@0
   655
/*! \brief Returns pointer to pixel buffer.
sl@0
   656
 *
sl@0
   657
 * \param buffer Handle of buffer
sl@0
   658
 */
sl@0
   659
void* CSurfaceStream::GetBufferPtrL(SymbianStreamBuffer aBuffer)
sl@0
   660
	 {
sl@0
   661
     TInt bufferIndex = BufferHandleToIndex(aBuffer);  
sl@0
   662
     Guard g1(iRefCountMutex);
sl@0
   663
     __ASSERT_DEBUG(iBufferInfo[bufferIndex].iRefCount > 0,
sl@0
   664
             (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
sl@0
   665
             
sl@0
   666
     switch (SurfaceId().Type())
sl@0
   667
         {
sl@0
   668
         case TSurfaceTypes::ESurfaceManagerSurface:
sl@0
   669
             {                         
sl@0
   670
             if (iBufferChunk.Handle() == 0)
sl@0
   671
                 {
sl@0
   672
                 RChunk threadChunk;
sl@0
   673
                 RSurfaceManager sm;
sl@0
   674
                 sm.Open();
sl@0
   675
                 TInt err = sm.MapSurface(iSurfaceId, threadChunk);
sl@0
   676
                 sm.Close();
sl@0
   677
                 CleanupClosePushL(threadChunk);
sl@0
   678
                 				 			
sl@0
   679
				 RChunk duplicateChunk;
sl@0
   680
				 duplicateChunk.SetHandle(threadChunk.Handle());
sl@0
   681
                 User::LeaveIfError(duplicateChunk.Duplicate(RThread(), EOwnerProcess));
sl@0
   682
 
sl@0
   683
                 iBufferChunk.SetHandle(duplicateChunk.Handle());
sl@0
   684
                 CleanupStack::PopAndDestroy(&threadChunk);
sl@0
   685
                 }
sl@0
   686
             break;
sl@0
   687
             }
sl@0
   688
	     case TSurfaceId::EScreenSurface:
sl@0
   689
	         {
sl@0
   690
	         if (iBufferChunk.Handle() == 0)
sl@0
   691
	             {
sl@0
   692
	             TInt val = 0;
sl@0
   693
	             TInt screenId = SurfaceId().iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField];
sl@0
   694
	             User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayMemoryHandle, val));
sl@0
   695
                
sl@0
   696
	             RChunk threadChunk;
sl@0
   697
				 CleanupClosePushL(threadChunk);
sl@0
   698
	             User::LeaveIfError(threadChunk.SetReturnedHandle(val));
sl@0
   699
sl@0
   700
				 RChunk duplicateChunk;
sl@0
   701
				 duplicateChunk.SetHandle(threadChunk.Handle());
sl@0
   702
				 User::LeaveIfError(duplicateChunk.Duplicate(RThread(), EOwnerProcess));
sl@0
   703
sl@0
   704
	             iBufferChunk.SetHandle(duplicateChunk.Handle());
sl@0
   705
	             CleanupStack::PopAndDestroy(&threadChunk);
sl@0
   706
	             }
sl@0
   707
	         break;
sl@0
   708
	         }
sl@0
   709
	     default:
sl@0
   710
	         User::Leave(KErrNotSupported);
sl@0
   711
	     }
sl@0
   712
	 
sl@0
   713
     TUint8 *pBufferStart = iBufferChunk.Base() + iBufferInfo[bufferIndex].iOffset;
sl@0
   714
     return static_cast<void*>(pBufferStart);	 
sl@0
   715
	 }
sl@0
   716
sl@0
   717
void CSurfaceStream::SetProtectionFlag(TBool aFlag)
sl@0
   718
	{
sl@0
   719
	iRefCountMutex.Wait();
sl@0
   720
	if (aFlag!=iProtected)
sl@0
   721
		{
sl@0
   722
		iProtected=aFlag;
sl@0
   723
		iRefCountMutex.Signal();
sl@0
   724
		if (aFlag)
sl@0
   725
			{
sl@0
   726
			AddReference();
sl@0
   727
			}
sl@0
   728
		else
sl@0
   729
			{
sl@0
   730
			ReleaseReference();
sl@0
   731
			}
sl@0
   732
		}
sl@0
   733
	else
sl@0
   734
		{
sl@0
   735
		iRefCountMutex.Signal();
sl@0
   736
		}
sl@0
   737
	}
sl@0
   738
sl@0
   739
TInt CSurfaceStream::BytesPerPixel(TUidPixelFormat aPixelFormat)
sl@0
   740
	{
sl@0
   741
	switch (aPixelFormat)
sl@0
   742
		{
sl@0
   743
		case EUidPixelFormatXRGB_8888:
sl@0
   744
		case EUidPixelFormatARGB_8888:
sl@0
   745
		case EUidPixelFormatBGRX_8888:
sl@0
   746
		case EUidPixelFormatXBGR_8888:
sl@0
   747
		case EUidPixelFormatBGRA_8888:
sl@0
   748
		case EUidPixelFormatABGR_8888:	
sl@0
   749
		case EUidPixelFormatABGR_8888_PRE:
sl@0
   750
		case EUidPixelFormatARGB_8888_PRE:
sl@0
   751
		case EUidPixelFormatBGRA_8888_PRE:
sl@0
   752
		case EUidPixelFormatARGB_2101010:
sl@0
   753
		case EUidPixelFormatABGR_2101010:
sl@0
   754
			return 4;
sl@0
   755
		case EUidPixelFormatBGR_888:
sl@0
   756
		case EUidPixelFormatRGB_888:
sl@0
   757
			return 3;
sl@0
   758
		case EUidPixelFormatXRGB_4444:
sl@0
   759
		case EUidPixelFormatARGB_4444:
sl@0
   760
		case EUidPixelFormatXBGR_4444:
sl@0
   761
		case EUidPixelFormatRGB_565:
sl@0
   762
		case EUidPixelFormatBGR_565:
sl@0
   763
		case EUidPixelFormatARGB_1555:
sl@0
   764
		case EUidPixelFormatXRGB_1555:
sl@0
   765
		case EUidPixelFormatARGB_8332:
sl@0
   766
		case EUidPixelFormatBGRX_5551:
sl@0
   767
		case EUidPixelFormatBGRA_5551:
sl@0
   768
		case EUidPixelFormatBGRA_4444:
sl@0
   769
		case EUidPixelFormatBGRX_4444:
sl@0
   770
		case EUidPixelFormatAP_88:
sl@0
   771
			return  2;
sl@0
   772
		case EUidPixelFormatRGB_332:
sl@0
   773
		case EUidPixelFormatBGR_332:
sl@0
   774
	    case EUidPixelFormatA_8:
sl@0
   775
	    case EUidPixelFormatL_8:
sl@0
   776
	        return  1;
sl@0
   777
		case EUidPixelFormatP_8:
sl@0
   778
			return -1;
sl@0
   779
	    case EUidPixelFormatP_4:
sl@0
   780
	    case EUidPixelFormatL_4:
sl@0
   781
	    	return -2;
sl@0
   782
	    case EUidPixelFormatL_2:
sl@0
   783
	    case EUidPixelFormatP_2:
sl@0
   784
	    	return -4;
sl@0
   785
	    case EUidPixelFormatL_1 :
sl@0
   786
            return -8;
sl@0
   787
		default:
sl@0
   788
			{
sl@0
   789
			return 0;
sl@0
   790
			}
sl@0
   791
		}
sl@0
   792
	}
sl@0
   793
sl@0
   794
SymbianStreamBuffer CSurfaceStream::IndexToReadHandle(TInt aIndex)
sl@0
   795
	{
sl@0
   796
	return static_cast<SymbianStreamBuffer>(aIndex + BUFFER_READ_HANDLE_BASE);
sl@0
   797
	}
sl@0
   798
sl@0
   799
SymbianStreamBuffer CSurfaceStream::IndexToWriteHandle(TInt aIndex)
sl@0
   800
	{
sl@0
   801
	return static_cast<SymbianStreamBuffer>(aIndex + BUFFER_WRITE_HANDLE_BASE);
sl@0
   802
	}
sl@0
   803
sl@0
   804
TInt CSurfaceStream::BufferHandleToIndex(SymbianStreamBuffer aBuff)
sl@0
   805
	{
sl@0
   806
	TInt retVal= (aBuff > 0) ? (aBuff&0xFF) : (aBuff - BUFFER_READ_HANDLE_BASE);
sl@0
   807
	__ASSERT_DEBUG(retVal>=0,User::Invariant());
sl@0
   808
	__ASSERT_DEBUG(retVal<iInfo.iBuffers,User::Invariant());
sl@0
   809
	return retVal;
sl@0
   810
	}
sl@0
   811
sl@0
   812
sl@0
   813
sl@0
   814
sl@0
   815
void CSurfaceStream::RequestComplete(TThreadId& aThreadId, TRequestStatus*& aRequestStatus, TInt& aGlobalIndexArray, TInt aStatus)
sl@0
   816
    {
sl@0
   817
    if (aRequestStatus)
sl@0
   818
        {
sl@0
   819
        if (aGlobalIndexArray != KInvalidIndex)
sl@0
   820
            {
sl@0
   821
            TGlobalNotification& globalNotification = iGlobalNotifications[aGlobalIndexArray];
sl@0
   822
            --globalNotification.iPendingNotifications;
sl@0
   823
            switch (aStatus)
sl@0
   824
                {
sl@0
   825
                case KErrNone:
sl@0
   826
                    globalNotification.iCompletedOkNotifications++;
sl@0
   827
                    break;
sl@0
   828
                case KErrOverflow:
sl@0
   829
                    globalNotification.iOverflowedNotifications++;
sl@0
   830
                    break;
sl@0
   831
                case KErrCancel:
sl@0
   832
                    globalNotification.iCanceledNotifications++;
sl@0
   833
                    break;
sl@0
   834
                case KErrNotVisible:
sl@0
   835
                    globalNotification.iNotVisibleNotifications++;
sl@0
   836
                    break;
sl@0
   837
                default:
sl@0
   838
                    globalNotification.iOtherNotifications++;
sl@0
   839
                }
sl@0
   840
            NFLOG(("### CSurfaceStream::RequestComplete globalRequestStatus[%d] iPendingNotifications(%d) "
sl@0
   841
                    "iCompletedOkNotifications(%d)"
sl@0
   842
                    "iOverflowedNotifications(%d)"
sl@0
   843
                    "iCanceledNotifications(%d)"
sl@0
   844
                    "iNotVisibleNotifications(%d)"
sl@0
   845
                    "iOtherNotifications(%d)"
sl@0
   846
                    "requestStatus(%p)",
sl@0
   847
                    aGlobalIndexArray, 
sl@0
   848
                    globalNotification.iPendingNotifications, 
sl@0
   849
                    globalNotification.iCompletedOkNotifications, 
sl@0
   850
                    globalNotification.iOverflowedNotifications,
sl@0
   851
                    globalNotification.iCanceledNotifications,
sl@0
   852
                    globalNotification.iNotVisibleNotifications,
sl@0
   853
                    globalNotification.iOtherNotifications,
sl@0
   854
                    aStatus));
sl@0
   855
            
sl@0
   856
            if (globalNotification.iStatus && globalNotification.iPendingNotifications == 0)
sl@0
   857
                {
sl@0
   858
                TInt status;
sl@0
   859
                if (globalNotification.iCompletedOkNotifications > 0)
sl@0
   860
                    {
sl@0
   861
                    status = KErrNone;
sl@0
   862
                    }
sl@0
   863
                else if (globalNotification.iOverflowedNotifications > 0)
sl@0
   864
                    {
sl@0
   865
                    status = KErrOverflow;
sl@0
   866
                    }
sl@0
   867
                else if (globalNotification.iNotVisibleNotifications > 0)
sl@0
   868
                    {
sl@0
   869
                    status = KErrNotVisible;
sl@0
   870
                    }
sl@0
   871
                else if (globalNotification.iCanceledNotifications > 0)
sl@0
   872
                    {
sl@0
   873
                    status = KErrCancel;
sl@0
   874
                    }
sl@0
   875
                else
sl@0
   876
                    {
sl@0
   877
                    status = KErrGeneral;
sl@0
   878
                    }
sl@0
   879
                    
sl@0
   880
                RThread thread;
sl@0
   881
                if (thread.Open(globalNotification.iThreadId) == KErrNone)
sl@0
   882
                    {
sl@0
   883
                    NFLOG(("### CSurfaceStream::RequestComplete globalIndex[%d] aRequestComplete(0x%x) status(%d)",
sl@0
   884
                            aGlobalIndexArray, iGlobalNotifications[aGlobalIndexArray].iStatus, status));
sl@0
   885
                    thread.RequestComplete(globalNotification.iStatus, status);
sl@0
   886
                    thread.Close();
sl@0
   887
                    iGlobalNotifications[aGlobalIndexArray].Reset();
sl@0
   888
                    }
sl@0
   889
                }
sl@0
   890
            }
sl@0
   891
        else
sl@0
   892
            {
sl@0
   893
            RThread thread;
sl@0
   894
            if (thread.Open(aThreadId) == KErrNone)
sl@0
   895
                {
sl@0
   896
                NFLOG(("### CSurfaceStream::RequestComplete aRequestStatus(0x%x) aThreadId(0x%x) aStatus(%d)",
sl@0
   897
                        aRequestStatus, aThreadId, aStatus));
sl@0
   898
                thread.RequestComplete(aRequestStatus, aStatus);
sl@0
   899
                thread.Close();
sl@0
   900
                }
sl@0
   901
            }
sl@0
   902
        aRequestStatus = NULL;
sl@0
   903
        aThreadId = 0;
sl@0
   904
        }
sl@0
   905
    aGlobalIndexArray = KInvalidIndex;
sl@0
   906
    }
sl@0
   907
sl@0
   908
int  CSurfaceStream::AddObserver(SymbianStreamCallback aObserver, 
sl@0
   909
                                 TInt32 aEvent,
sl@0
   910
                                 TInt32 aScreenNumber,
sl@0
   911
                                 void* aData)
sl@0
   912
     {
sl@0
   913
     if (!(aEvent & ESOWF_AllEventsMask) || !aData)
sl@0
   914
         {
sl@0
   915
         // early exit if the parameters are invalid
sl@0
   916
         return KErrArgument;
sl@0
   917
         }
sl@0
   918
     
sl@0
   919
     TInt  errRet = KErrNone;
sl@0
   920
     TCallBackEntry newEntry;
sl@0
   921
     
sl@0
   922
     Guard g2(iCallBacksMutex);
sl@0
   923
     Guard g1(iRefCountMutex);
sl@0
   924
     
sl@0
   925
     // Let's do the check that we dont have an other similar observer already inserted
sl@0
   926
     // traverse the whole aobservers list to see if there is already an observer in place
sl@0
   927
     TInt  idx = iCallBacks.Count();
sl@0
   928
     while(idx--)
sl@0
   929
         {
sl@0
   930
         if (iCallBacks[idx].iEventMask == aEvent)
sl@0
   931
             {
sl@0
   932
             switch (aEvent)
sl@0
   933
                 {
sl@0
   934
                 case ESOWF_EventAvailable:
sl@0
   935
                 case ESOWF_EventDisplayed:
sl@0
   936
                 case ESOWF_EventDisplayedX:
sl@0
   937
                     // these are events related to a context and identified by a screen number
sl@0
   938
                     if (iCallBacks[idx].iScreenNumber == aScreenNumber)
sl@0
   939
                         {
sl@0
   940
                         // nothing else to do, the entry is already created
sl@0
   941
                         return KErrOverflow;
sl@0
   942
                         }
sl@0
   943
                     break;
sl@0
   944
                     
sl@0
   945
                 case ESOWF_EventComposed:
sl@0
   946
                 case ESOWF_EventUpdated:
sl@0
   947
                     if (iCallBacks[idx].iCallBackClientParam == aData)
sl@0
   948
                         {
sl@0
   949
                         // nothing else to do, the entry is already created
sl@0
   950
                         return KErrOverflow;
sl@0
   951
                         }
sl@0
   952
                     break;
sl@0
   953
                     
sl@0
   954
                 default:
sl@0
   955
                     // something really unexpected, let's invalidate the entry
sl@0
   956
                     // possible memomry leaks but we are, still, alive and running.
sl@0
   957
                     iCallBacks[idx].Reset();
sl@0
   958
                     break;
sl@0
   959
                 }
sl@0
   960
             }
sl@0
   961
         }
sl@0
   962
     
sl@0
   963
     // we need to add a new observer to the list
sl@0
   964
    newEntry.iCallBackFunction = aObserver;
sl@0
   965
    newEntry.iEventMask = aEvent;
sl@0
   966
    newEntry.iScreenNumber = aScreenNumber;
sl@0
   967
    TInt trapErr;
sl@0
   968
    switch (aEvent)
sl@0
   969
        {
sl@0
   970
        case ESOWF_EventUpdated:
sl@0
   971
        case ESOWF_EventComposed:
sl@0
   972
            newEntry.iCallBackClientParam = aData;
sl@0
   973
            break;
sl@0
   974
        
sl@0
   975
        case ESOWF_EventAvailable:
sl@0
   976
            {
sl@0
   977
            TNotificationAvailable* available = NULL;
sl@0
   978
            TRAP(trapErr,available = new(ELeave) TNotificationAvailable());
sl@0
   979
            if (trapErr != KErrNone)
sl@0
   980
                {
sl@0
   981
                return trapErr;
sl@0
   982
                }
sl@0
   983
            ResetCallBackData(available, aEvent);
sl@0
   984
            available->iSerialNumber = KInitialContextSerialNumber;
sl@0
   985
            newEntry.iCallBackClientParam = available;
sl@0
   986
            }
sl@0
   987
            break;
sl@0
   988
        
sl@0
   989
        case ESOWF_EventDisplayed:
sl@0
   990
            {
sl@0
   991
            TNotificationDisplayed* displayed = NULL;
sl@0
   992
            TRAP(trapErr,displayed = new(ELeave) TNotificationDisplayed());
sl@0
   993
            if (trapErr != KErrNone)
sl@0
   994
                {
sl@0
   995
                return trapErr;
sl@0
   996
                }
sl@0
   997
            ResetCallBackData(displayed, aEvent);
sl@0
   998
            displayed->iSerialNumber = KInitialContextSerialNumber;
sl@0
   999
            newEntry.iCallBackClientParam = displayed;
sl@0
  1000
            }
sl@0
  1001
            break;
sl@0
  1002
        
sl@0
  1003
        case ESOWF_EventDisplayedX:
sl@0
  1004
            {
sl@0
  1005
            TNotificationDisplayedX* displayedX = NULL;
sl@0
  1006
            TRAP(trapErr,displayedX = new(ELeave) TNotificationDisplayedX()); 
sl@0
  1007
            if (trapErr != KErrNone)
sl@0
  1008
                {
sl@0
  1009
                return trapErr;
sl@0
  1010
                }
sl@0
  1011
            ResetCallBackData(displayedX, aEvent);
sl@0
  1012
            displayedX->iSerialNumber = KInitialContextSerialNumber;
sl@0
  1013
            newEntry.iCallBackClientParam = displayedX;
sl@0
  1014
            }
sl@0
  1015
            break;
sl@0
  1016
        
sl@0
  1017
        default:
sl@0
  1018
            return KErrArgument;
sl@0
  1019
        }
sl@0
  1020
     
sl@0
  1021
     // look for an entry that already exists
sl@0
  1022
     idx = iCallBacks.Count();
sl@0
  1023
     
sl@0
  1024
     while(idx--)
sl@0
  1025
         {
sl@0
  1026
         // the free entry positions are identified using event mask
sl@0
  1027
         if (iCallBacks[idx].iEventMask == ESOWF_NoEvent) break;
sl@0
  1028
         }
sl@0
  1029
     
sl@0
  1030
     if (idx > -1)
sl@0
  1031
         {
sl@0
  1032
         // ok, we got an existing, free entry
sl@0
  1033
         iCallBacks[idx] = newEntry;
sl@0
  1034
         }
sl@0
  1035
     else
sl@0
  1036
         {
sl@0
  1037
         errRet = iCallBacks.Append(newEntry);
sl@0
  1038
         if (errRet != KErrNone)
sl@0
  1039
             {
sl@0
  1040
             return errRet;
sl@0
  1041
             }
sl@0
  1042
         }
sl@0
  1043
sl@0
  1044
     switch (aEvent)
sl@0
  1045
         {
sl@0
  1046
         case ESOWF_EventAvailable:
sl@0
  1047
             iNumberOfScreenAttachedAvailableNotif++;
sl@0
  1048
             break;
sl@0
  1049
             
sl@0
  1050
         case ESOWF_EventDisplayed:
sl@0
  1051
             iNumberOfScreenAttachedDisplayedNotif++;
sl@0
  1052
             break;
sl@0
  1053
             
sl@0
  1054
         case ESOWF_EventDisplayedX:
sl@0
  1055
             iNumberOfScreenAttachedDisplayedXNotif++;
sl@0
  1056
             break;
sl@0
  1057
             
sl@0
  1058
         default:
sl@0
  1059
             break;
sl@0
  1060
         
sl@0
  1061
         }
sl@0
  1062
     
sl@0
  1063
     return errRet;
sl@0
  1064
     }
sl@0
  1065
sl@0
  1066
sl@0
  1067
int CSurfaceStream::RemoveObserver(TInt32 aEvents, void* aData)
sl@0
  1068
    {
sl@0
  1069
    NFLOG(("ENTER ###CSurfaceStream::RemoveObserver() events(%d) data(0x%x)", aEvents, aData));
sl@0
  1070
    if (!(aEvents & ESOWF_AllEventsMask))
sl@0
  1071
    {
sl@0
  1072
        NFLOG(("EXIT ###CSurfaceStream::RemoveObserver() ERROR: KErrArgument"));
sl@0
  1073
        return KErrArgument;
sl@0
  1074
    }
sl@0
  1075
     
sl@0
  1076
    Guard g2(iCallBacksMutex);
sl@0
  1077
    Guard g1(iRefCountMutex);
sl@0
  1078
    
sl@0
  1079
    TInt32 notFoundEvent = aEvents;
sl@0
  1080
    TInt count = iCallBacks.Count();
sl@0
  1081
    TInt32 susScreenNumber = KNoAssociatedScreenNumber;
sl@0
  1082
    
sl@0
  1083
    if (aData)
sl@0
  1084
        {
sl@0
  1085
        susScreenNumber = *(((TInt32*)aData));
sl@0
  1086
        }
sl@0
  1087
        
sl@0
  1088
    while (count-- && notFoundEvent)
sl@0
  1089
        {
sl@0
  1090
        TInt32 currentEvent = iCallBacks[count].iEventMask;
sl@0
  1091
        if (currentEvent & aEvents)
sl@0
  1092
            {
sl@0
  1093
            void* callBackData = iCallBacks[count].iCallBackClientParam;
sl@0
  1094
            switch (currentEvent)
sl@0
  1095
                {
sl@0
  1096
                case ESOWF_EventDisplayed:
sl@0
  1097
                    if (callBackData && (!aData || (iCallBacks[count].iScreenNumber == susScreenNumber)))
sl@0
  1098
                        {
sl@0
  1099
                        Displayed(ESOWF_ObserverCancel, iCallBacks[count].iScreenNumber, NULL, callBackData, NULL);
sl@0
  1100
                        delete (TNotificationDisplayed*) callBackData;
sl@0
  1101
                        iCallBacks[count].Reset();
sl@0
  1102
                        if (iNumberOfScreenAttachedDisplayedNotif > 0)
sl@0
  1103
                            {
sl@0
  1104
                            iNumberOfScreenAttachedDisplayedNotif--;
sl@0
  1105
                            }
sl@0
  1106
                        notFoundEvent &= ~currentEvent;
sl@0
  1107
                        }
sl@0
  1108
                    break;
sl@0
  1109
             
sl@0
  1110
                case ESOWF_EventAvailable:
sl@0
  1111
                    if (callBackData && (!aData || (iCallBacks[count].iScreenNumber == susScreenNumber)))
sl@0
  1112
                        {
sl@0
  1113
                        Available(ESOWF_ObserverCancel, iCallBacks[count].iScreenNumber, NULL, callBackData, NULL);
sl@0
  1114
                        delete (TNotificationAvailable*) callBackData;
sl@0
  1115
                        iCallBacks[count].Reset();
sl@0
  1116
                        if (iNumberOfScreenAttachedAvailableNotif > 0)
sl@0
  1117
                            {
sl@0
  1118
                            iNumberOfScreenAttachedAvailableNotif--;
sl@0
  1119
                            }
sl@0
  1120
                        notFoundEvent &= ~currentEvent;
sl@0
  1121
                        }                       
sl@0
  1122
                    break;
sl@0
  1123
             
sl@0
  1124
                case ESOWF_EventDisplayedX:
sl@0
  1125
                    if (callBackData && (!aData || (iCallBacks[count].iScreenNumber == susScreenNumber)))
sl@0
  1126
                        {
sl@0
  1127
                        DisplayedXTimes(ESOWF_ObserverCancel, iCallBacks[count].iScreenNumber, NULL, callBackData, NULL);
sl@0
  1128
                        delete (TNotificationDisplayedX*) callBackData;
sl@0
  1129
                        iCallBacks[count].Reset();
sl@0
  1130
                        if (iNumberOfScreenAttachedDisplayedXNotif)
sl@0
  1131
                            {
sl@0
  1132
                            iNumberOfScreenAttachedDisplayedXNotif--;
sl@0
  1133
                            }
sl@0
  1134
                        notFoundEvent &= ~currentEvent;
sl@0
  1135
                        }                   
sl@0
  1136
                    break;
sl@0
  1137
             
sl@0
  1138
                case ESOWF_EventComposed:
sl@0
  1139
                    if (!aData || (aData == iCallBacks[count].iCallBackClientParam))
sl@0
  1140
                        {
sl@0
  1141
                        // just in case that we have to delete the call back, we try, first to execute it
sl@0
  1142
                        // avoiding in this way some deadlocks in CT code
sl@0
  1143
                        if (iCallBacks[count].iCallBackFunction && iCallBacks[count].iCallBackClientParam)
sl@0
  1144
                            {
sl@0
  1145
                            iCallBacks[count].iCallBackFunction(ToHandle(), 
sl@0
  1146
                                                                ESOWF_EventComposed, 
sl@0
  1147
                                                                iCallBacks[count].iCallBackClientParam, 
sl@0
  1148
                                                                NULL);
sl@0
  1149
                            }
sl@0
  1150
                        iCallBacks[count].Reset();
sl@0
  1151
                        notFoundEvent &= ~currentEvent;
sl@0
  1152
                        }
sl@0
  1153
                    break;
sl@0
  1154
                
sl@0
  1155
                case ESOWF_EventUpdated:
sl@0
  1156
                    if (!aData || (aData == iCallBacks[count].iCallBackClientParam))
sl@0
  1157
                        {
sl@0
  1158
                        if (iCallBacks[count].iScreenNumber != KNoAssociatedScreenNumber)
sl@0
  1159
                            {
sl@0
  1160
                            susScreenNumber = iCallBacks[count].iScreenNumber;
sl@0
  1161
                            iCallBacks[count].Reset();
sl@0
  1162
                            notFoundEvent &= ~currentEvent;
sl@0
  1163
                            
sl@0
  1164
                            // Reseting variables to loop back and remove SUS events.
sl@0
  1165
                            notFoundEvent |= ESOWF_SUSEventsMask;
sl@0
  1166
                            aEvents = ESOWF_SUSEventsMask;
sl@0
  1167
                            count = iCallBacks.Count();
sl@0
  1168
                            }
sl@0
  1169
                        else
sl@0
  1170
                            {
sl@0
  1171
                            iCallBacks[count].Reset();
sl@0
  1172
                            notFoundEvent &= ~currentEvent;
sl@0
  1173
                            }
sl@0
  1174
                        }
sl@0
  1175
                    break;
sl@0
  1176
                
sl@0
  1177
                default:
sl@0
  1178
                    break;
sl@0
  1179
                }
sl@0
  1180
            }
sl@0
  1181
        }
sl@0
  1182
    
sl@0
  1183
    NFLOG(("EXIT ###CSurfaceStream::CancelNotifications() err(%d)", notFoundEvent ? KErrNotFound : KErrNone));
sl@0
  1184
    return (notFoundEvent ? KErrNotFound : KErrNone);
sl@0
  1185
    }
sl@0
  1186
sl@0
  1187
TInt CSurfaceStream::NotifyObservers(TInt32 aEvent)
sl@0
  1188
    {
sl@0
  1189
    NFLOG(("### ENTER CSurfaceStream::NotifyObservers()"));
sl@0
  1190
    TInt err = KErrNotFound;
sl@0
  1191
    
sl@0
  1192
    Guard g2(iCallBacksMutex);
sl@0
  1193
    TCallBackEntry localCallBackEntry;
sl@0
  1194
    
sl@0
  1195
    for (TInt i = 0; i < iCallBacks.Count(); ++i)
sl@0
  1196
        {
sl@0
  1197
        localCallBackEntry = iCallBacks[i];
sl@0
  1198
        if (iCallBacks[i].iEventMask & aEvent && 
sl@0
  1199
            iCallBacks[i].iCallBackFunction) 
sl@0
  1200
            {
sl@0
  1201
            err = KErrNone;
sl@0
  1202
            NFLOG(("### EXIT CSurfaceStream::NotifyObservers() callback(%d)", iCallBacks[i].iEventMask));
sl@0
  1203
            localCallBackEntry.iCallBackFunction(ToHandle(), 
sl@0
  1204
                                                 iCallBacks[i].iEventMask, 
sl@0
  1205
                                                 localCallBackEntry.iCallBackClientParam, 
sl@0
  1206
                                                 NULL);
sl@0
  1207
            }
sl@0
  1208
        }
sl@0
  1209
    NFLOG(("### EXIT CSurfaceStream::NotifyObservers() err(%d)", err));
sl@0
  1210
    return err;
sl@0
  1211
    }
sl@0
  1212
sl@0
  1213
TBool CSurfaceStream::NotifyComposerContext(TInt32 aScreenNumber, TInt aOp, SYMOWF_CONTENT_UPDATED_PARAM* aParam)
sl@0
  1214
    {
sl@0
  1215
    NFLOG(("### ENTER CSurfaceStream::NotifyComposerContext()"));
sl@0
  1216
    TCallBackEntry entry;
sl@0
  1217
    TBool ret = EFalse;
sl@0
  1218
    for(TInt i = 0; i < iCallBacks.Count(); i++)
sl@0
  1219
        {
sl@0
  1220
        if (iCallBacks[i].iEventMask == ESOWF_EventUpdated && 
sl@0
  1221
            iCallBacks[i].iCallBackFunction && 
sl@0
  1222
            (((iCallBacks[i].iScreenNumber == KNoAssociatedScreenNumber) && (aOp != SYM_CONTENT_UPDATE_BEGIN)) ||
sl@0
  1223
             ((aScreenNumber == KNoAssociatedScreenNumber) && (aOp != SYM_CONTENT_UPDATE_BEGIN)) ||
sl@0
  1224
             iCallBacks[i].iScreenNumber == aScreenNumber))
sl@0
  1225
            {
sl@0
  1226
            entry = iCallBacks[i];
sl@0
  1227
            iRefCountMutex.Signal();
sl@0
  1228
            NFLOG(("###CSurfaceStream::NotifyComposerContext() ESOWF_EventUpdated aParam(%d)", aParam? aParam->id: -1));
sl@0
  1229
            entry.iCallBackFunction(ToHandle(), ESOWF_EventUpdated, entry.iCallBackClientParam, aParam);
sl@0
  1230
            ret = ETrue;
sl@0
  1231
			// We are meant to hold this lock when we leave this function so coverity warning is false
sl@0
  1232
			//coverity[lock]
sl@0
  1233
            iRefCountMutex.Wait();
sl@0
  1234
            }
sl@0
  1235
        }
sl@0
  1236
    NFLOG(("### EXIT CSurfaceStream::NotifyComposerContext() ret(%d)", ret));
sl@0
  1237
    return ret;
sl@0
  1238
    }
sl@0
  1239
sl@0
  1240
TBool CSurfaceStream::StartUpdateNotifications(TInt aScreenNumber, SYMOWF_CONTENT_UPDATED_PARAM& param)
sl@0
  1241
    {
sl@0
  1242
    NFLOG(("### CSurfaceStream::StartUpdateNotifications()"));
sl@0
  1243
    param.id = SYM_CONTENT_UPDATE_BEGIN;
sl@0
  1244
    param.length = sizeof (param);
sl@0
  1245
    param.par = 0;
sl@0
  1246
    param.serialNumber = KNoAssociatedScreenNumber;
sl@0
  1247
    param.immediateAvailable = 0;
sl@0
  1248
    return NotifyComposerContext(aScreenNumber, SYM_CONTENT_UPDATE_BEGIN, &param);
sl@0
  1249
    }
sl@0
  1250
sl@0
  1251
TBool CSurfaceStream::EndUpdateNotifications(TInt aScreenNum, TInt aBufferNum, TInt32 aUpdatedFlags, const TRegion* aRegion)
sl@0
  1252
    {
sl@0
  1253
    (void)aScreenNum;
sl@0
  1254
    (void)aRegion;
sl@0
  1255
    NFLOG(("### CSurfaceStream::EndUpdateNotifications()"));
sl@0
  1256
    if (aBufferNum < 0 || aBufferNum >= iInfo.iBuffers)
sl@0
  1257
        {
sl@0
  1258
        return EFalse;
sl@0
  1259
        }
sl@0
  1260
    
sl@0
  1261
    if (iAcquiredWriteBuffer != WFC_INVALID_HANDLE)
sl@0
  1262
        {
sl@0
  1263
        iAcquiredWriteBuffer = BUFFER_WRITE_UPDATE_OVERWRITE;
sl@0
  1264
        }
sl@0
  1265
    
sl@0
  1266
    SetReadBufferIndex(aBufferNum);
sl@0
  1267
    
sl@0
  1268
    SYMOWF_CONTENT_UPDATED_PARAM param;
sl@0
  1269
    param.length = sizeof (param);
sl@0
  1270
    param.id = SYM_CONTENT_UPDATE_END;
sl@0
  1271
    param.par = aUpdatedFlags;
sl@0
  1272
    return NotifyComposerContext(aScreenNum, SYM_CONTENT_UPDATE_END, &param);
sl@0
  1273
    }
sl@0
  1274
sl@0
  1275
TBool CSurfaceStream::UpdateNotifications(TInt aScreenNum, 
sl@0
  1276
                                         TInt aBufferNum, 
sl@0
  1277
                                         TInt32 aUpdatedFlags, 
sl@0
  1278
                                         const TRegion* aRegion)
sl@0
  1279
    {
sl@0
  1280
    (void)aScreenNum;
sl@0
  1281
    (void)aRegion;
sl@0
  1282
    NFLOG(("### CSurfaceStream::UpdateNotifications()"));
sl@0
  1283
    if (aBufferNum < 0 || aBufferNum >= iInfo.iBuffers)
sl@0
  1284
        {
sl@0
  1285
        return EFalse;
sl@0
  1286
        }
sl@0
  1287
    
sl@0
  1288
    if (iAcquiredWriteBuffer != WFC_INVALID_HANDLE)
sl@0
  1289
        {
sl@0
  1290
        iAcquiredWriteBuffer = BUFFER_WRITE_UPDATE_OVERWRITE;
sl@0
  1291
        }
sl@0
  1292
    
sl@0
  1293
    SetReadBufferIndex(aBufferNum);
sl@0
  1294
    
sl@0
  1295
    SYMOWF_CONTENT_UPDATED_PARAM param;
sl@0
  1296
    param.length = sizeof (param);
sl@0
  1297
    param.id = SYM_CONTENT_UPDATE;
sl@0
  1298
    param.par = aUpdatedFlags;
sl@0
  1299
    return NotifyComposerContext(aScreenNum, SYM_CONTENT_UPDATE, &param);
sl@0
  1300
    }
sl@0
  1301
sl@0
  1302
void CSurfaceStream::SetNewNotifications(TInt            aBuffer,
sl@0
  1303
                                         TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
sl@0
  1304
                                         TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
sl@0
  1305
                                         TRequestStatus* aStatusConsumed, const TRegion* aRegion, 
sl@0
  1306
                                         TInt32          aScreenNumber)
sl@0
  1307
    {
sl@0
  1308
    NFLOG(("### ENTER * CSurfaceStream::SetNewNotifications()"));
sl@0
  1309
    Guard g2(iCallBacksMutex);
sl@0
  1310
    Guard g1(iRefCountMutex);
sl@0
  1311
    if (aScreenNumber == KAllScreens)
sl@0
  1312
        {
sl@0
  1313
        SetAllNotifications(aBuffer, 
sl@0
  1314
                            aStatusDisplayed, aTimeStamp, 
sl@0
  1315
                            aStatusDispXTimes, aDisplayedXTimes, 
sl@0
  1316
                            aStatusConsumed, aRegion);
sl@0
  1317
        }
sl@0
  1318
    else
sl@0
  1319
        {
sl@0
  1320
        TNewGlobalNotifications noGlobalNotifications;
sl@0
  1321
        SetNotifications(aBuffer, 
sl@0
  1322
                         aStatusDisplayed, aTimeStamp, 
sl@0
  1323
                         aStatusDispXTimes, aDisplayedXTimes, 
sl@0
  1324
                         aStatusConsumed, aRegion, 
sl@0
  1325
                         aScreenNumber, noGlobalNotifications);
sl@0
  1326
        }
sl@0
  1327
    NFLOG(("### EXIT * CSurfaceStream::SetNewNotifications()"));
sl@0
  1328
    }
sl@0
  1329
sl@0
  1330
sl@0
  1331
void CSurfaceStream::SetNotifications(TInt            aBuffer,
sl@0
  1332
                                      TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
sl@0
  1333
                                      TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
sl@0
  1334
                                      TRequestStatus* aStatusConsumed, const TRegion* aRegion, 
sl@0
  1335
                                      TInt32          aScreenNumber, const TNewGlobalNotifications& aGlobalNotifications)
sl@0
  1336
    {
sl@0
  1337
    NFLOG(("### ENTER * CSurfaceStream::SetNotifications()"));
sl@0
  1338
    TInt32 eventsFound = 0;
sl@0
  1339
    TInt32 eventsReceived = 0;
sl@0
  1340
    TInt32 eventsToProcess = 0;
sl@0
  1341
    TInt32 contextUpdate = 0;
sl@0
  1342
    // let's take in evidence the events we have to process
sl@0
  1343
    if (aStatusConsumed)
sl@0
  1344
        {
sl@0
  1345
        eventsReceived |= ESOWF_EventAvailable;
sl@0
  1346
        }
sl@0
  1347
    if (aStatusDisplayed)
sl@0
  1348
        {
sl@0
  1349
        eventsReceived |= ESOWF_EventDisplayed;
sl@0
  1350
        }
sl@0
  1351
    if (aStatusDispXTimes)
sl@0
  1352
        {
sl@0
  1353
        eventsReceived |= ESOWF_EventDisplayedX;
sl@0
  1354
        }
sl@0
  1355
    
sl@0
  1356
    TInt availableIndex = -1;
sl@0
  1357
    TInt displayedIndex = -1;
sl@0
  1358
    TInt displayedXIndex = -1;
sl@0
  1359
    
sl@0
  1360
    TInt32 serialNumber = KNoAssociatedScreenNumber;
sl@0
  1361
    TBool immediateAvailable = EFalse;
sl@0
  1362
    TInt32 immediateVisibility = SYM_CONTENT_VISIBLE_NOT_SET;
sl@0
  1363
    
sl@0
  1364
    // guard acquiring/release of the update lock of the composer
sl@0
  1365
    // acquire the update lock of the composer and retrive the composer state info
sl@0
  1366
    SYMOWF_CONTENT_UPDATED_PARAM param;
sl@0
  1367
    TBool startUpdateNotification = StartUpdateNotifications(aScreenNumber, param);
sl@0
  1368
    immediateAvailable = param.immediateAvailable && ETrue;
sl@0
  1369
    immediateVisibility = param.immediateVisibility;
sl@0
  1370
    serialNumber = param.serialNumber;
sl@0
  1371
    
sl@0
  1372
    
sl@0
  1373
    // we take, initially in consideration "available" even if we might not have received a consumed request status
sl@0
  1374
    eventsToProcess = 0;
sl@0
  1375
    
sl@0
  1376
    // we try to figure out which are the events we have to process and to get hold of their position
sl@0
  1377
    // in the observers array, in order to avoid traversing it again
sl@0
  1378
    TInt idx = iCallBacks.Count();
sl@0
  1379
    //we will intend to mark the visited events, as an optimisation
sl@0
  1380
    TInt32 eventsToCheck = eventsReceived | ESOWF_EventAvailable;
sl@0
  1381
    TInt32 currentEvent = 0;
sl@0
  1382
    while(--idx > -1 && eventsToCheck)
sl@0
  1383
        {
sl@0
  1384
        currentEvent = iCallBacks[idx].iEventMask;
sl@0
  1385
        if ((currentEvent & eventsToCheck) && (iCallBacks[idx].iScreenNumber == aScreenNumber))
sl@0
  1386
            {
sl@0
  1387
            switch (currentEvent)
sl@0
  1388
                {
sl@0
  1389
                case ESOWF_EventAvailable:
sl@0
  1390
                    // mark observer visited
sl@0
  1391
                    eventsToCheck &= ~currentEvent;
sl@0
  1392
                    // mark the events found only if the corresponding status request has been recived
sl@0
  1393
                    eventsFound |= (currentEvent & eventsReceived);
sl@0
  1394
                    // reset the events to process mask
sl@0
  1395
                    eventsToProcess &= ~currentEvent;
sl@0
  1396
                    {
sl@0
  1397
                    TNotificationAvailable* available = (TNotificationAvailable*) iCallBacks[idx].iCallBackClientParam;
sl@0
  1398
                    if (available && (aStatusConsumed || available->iStatus || available->iNewStatus))
sl@0
  1399
                        {
sl@0
  1400
                        // set the mask of the events to be processed because we have either to overflow some available request
sl@0
  1401
                        // statuses, or to process them further
sl@0
  1402
                        eventsToProcess |= ESOWF_EventAvailable;
sl@0
  1403
                        availableIndex = idx;
sl@0
  1404
                        }
sl@0
  1405
                    }
sl@0
  1406
                    break;
sl@0
  1407
                    
sl@0
  1408
                case ESOWF_EventDisplayed:
sl@0
  1409
                    // mark observer visited
sl@0
  1410
                    eventsFound |= currentEvent;
sl@0
  1411
                    eventsToProcess |= currentEvent;
sl@0
  1412
                    eventsToCheck &= ~currentEvent;
sl@0
  1413
                    displayedIndex = idx;
sl@0
  1414
                    break;
sl@0
  1415
                    
sl@0
  1416
                case ESOWF_EventDisplayedX:
sl@0
  1417
                    // mark observer visited
sl@0
  1418
                    eventsFound |= currentEvent;
sl@0
  1419
                    eventsToProcess |= currentEvent;
sl@0
  1420
                    eventsToCheck &= ~currentEvent;
sl@0
  1421
                    displayedXIndex = idx;
sl@0
  1422
                    break;
sl@0
  1423
                    
sl@0
  1424
                default:
sl@0
  1425
                    Panic(EOwfSymbianUnexpectedObserverId);
sl@0
  1426
                    break;
sl@0
  1427
                }
sl@0
  1428
            }
sl@0
  1429
        }
sl@0
  1430
    
sl@0
  1431
    NFLOG(("### CSurfaceStream::SetNotifications eventsToProcess(0x%x)", eventsToProcess));
sl@0
  1432
    if (eventsToProcess)
sl@0
  1433
        {
sl@0
  1434
        
sl@0
  1435
        // from this momment on, the composer cannot process any notifications related to this stream
sl@0
  1436
        
sl@0
  1437
        ContentUpdatedParams updateParameters(aBuffer, aStatusDisplayed, aTimeStamp,
sl@0
  1438
                                              aStatusDispXTimes, aDisplayedXTimes,
sl@0
  1439
                                              aStatusConsumed, aRegion, 
sl@0
  1440
                                              immediateAvailable, immediateVisibility,
sl@0
  1441
                                              aGlobalNotifications);
sl@0
  1442
        
sl@0
  1443
        // process the observer corresponding to aStatusConsumed request status
sl@0
  1444
        if ((ESOWF_EventAvailable & eventsToProcess) && (availableIndex > -1))
sl@0
  1445
            {
sl@0
  1446
            Available(ESOWF_ObserverProcessing, 
sl@0
  1447
                      serialNumber, 
sl@0
  1448
                      &updateParameters, 
sl@0
  1449
                      iCallBacks[availableIndex].iCallBackClientParam, 
sl@0
  1450
                      &contextUpdate);
sl@0
  1451
            }
sl@0
  1452
        
sl@0
  1453
        // process the observer corresponding to aStatusDisplayed request status
sl@0
  1454
        if ((ESOWF_EventDisplayed & eventsToProcess) && (displayedIndex > -1))
sl@0
  1455
            {
sl@0
  1456
            Displayed(ESOWF_ObserverProcessing, 
sl@0
  1457
                      serialNumber, 
sl@0
  1458
                      &updateParameters, 
sl@0
  1459
                      iCallBacks[displayedIndex].iCallBackClientParam, 
sl@0
  1460
                      &contextUpdate);
sl@0
  1461
            }
sl@0
  1462
        
sl@0
  1463
        // process the observer corresponding to aStatusDispXTimes request status
sl@0
  1464
        if ((ESOWF_EventDisplayedX & eventsToProcess) && (displayedXIndex > -1))
sl@0
  1465
            {
sl@0
  1466
            DisplayedXTimes(ESOWF_ObserverProcessing, 
sl@0
  1467
                            serialNumber, 
sl@0
  1468
                            &updateParameters, 
sl@0
  1469
                            iCallBacks[displayedXIndex].iCallBackClientParam, 
sl@0
  1470
                            &contextUpdate);
sl@0
  1471
            }
sl@0
  1472
        
sl@0
  1473
        }
sl@0
  1474
    
sl@0
  1475
    if (startUpdateNotification)
sl@0
  1476
        {
sl@0
  1477
        EndUpdateNotifications(aScreenNumber, aBuffer, contextUpdate, aRegion);
sl@0
  1478
        }
sl@0
  1479
    else
sl@0
  1480
        {
sl@0
  1481
        UpdateNotifications(aScreenNumber, aBuffer, contextUpdate, aRegion);
sl@0
  1482
        }
sl@0
  1483
    
sl@0
  1484
    if (eventsReceived != eventsFound)
sl@0
  1485
        {
sl@0
  1486
        if (aStatusConsumed && !(eventsFound & ESOWF_EventAvailable))
sl@0
  1487
            {
sl@0
  1488
            User::RequestComplete(aStatusConsumed, KErrCancel);
sl@0
  1489
            }
sl@0
  1490
        
sl@0
  1491
        if (aStatusDisplayed && !(eventsFound & ESOWF_EventDisplayed))
sl@0
  1492
            {
sl@0
  1493
            *aTimeStamp = 0;
sl@0
  1494
            User::RequestComplete(aStatusDisplayed, KErrCancel);
sl@0
  1495
            }
sl@0
  1496
        
sl@0
  1497
        if (aStatusDispXTimes && !(eventsFound & ESOWF_EventDisplayedX))
sl@0
  1498
            {
sl@0
  1499
            User::RequestComplete(aStatusDispXTimes, KErrCancel);
sl@0
  1500
            }
sl@0
  1501
        }
sl@0
  1502
    NFLOG(("### EXIT * CSurfaceStream::SetNotifications()"));
sl@0
  1503
    }
sl@0
  1504
sl@0
  1505
TInt CSurfaceStream::AddNewGlobalNotification(TRequestStatus* aStatusDisplayed, TInt aAssociatedScreens)
sl@0
  1506
    {
sl@0
  1507
    TInt maxIdx = iGlobalNotifications.Count();
sl@0
  1508
    TInt retIdx = KInvalidIndex;
sl@0
  1509
    for (TInt i = 0; i < maxIdx; i++)
sl@0
  1510
        {
sl@0
  1511
        if (iGlobalNotifications[i].iStatus == NULL)
sl@0
  1512
            {
sl@0
  1513
            NFLOG(("### ENTER * CSurfaceStream::AddNewGlobalNotification found free idx(%d)", i));
sl@0
  1514
            retIdx = i;
sl@0
  1515
            break;
sl@0
  1516
            }
sl@0
  1517
        }
sl@0
  1518
    
sl@0
  1519
    if (retIdx == KInvalidIndex)
sl@0
  1520
        {
sl@0
  1521
        TGlobalNotification newNotification;
sl@0
  1522
        if (iGlobalNotifications.Append(newNotification) == KErrNone)
sl@0
  1523
            {
sl@0
  1524
            retIdx = iGlobalNotifications.Count() - 1;
sl@0
  1525
            }
sl@0
  1526
        }
sl@0
  1527
    
sl@0
  1528
    if (retIdx != KInvalidIndex)
sl@0
  1529
        {
sl@0
  1530
        NFLOG(("### ENTER * CSurfaceStream::AddNewGlobalNotification populating idx(%d, status(%p) associated screens=0x%x)", retIdx, aStatusDisplayed, aAssociatedScreens));
sl@0
  1531
        iGlobalNotifications[retIdx].Reset();
sl@0
  1532
        iGlobalNotifications[retIdx].iStatus = aStatusDisplayed;
sl@0
  1533
        iGlobalNotifications[retIdx].iThreadId = RThread().Id();
sl@0
  1534
        iGlobalNotifications[retIdx].iPendingNotifications = aAssociatedScreens;
sl@0
  1535
        }
sl@0
  1536
    
sl@0
  1537
    return retIdx;
sl@0
  1538
    }
sl@0
  1539
sl@0
  1540
void CSurfaceStream::SetAllNotifications(TInt            aBuffer,
sl@0
  1541
                                         TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
sl@0
  1542
                                         TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
sl@0
  1543
                                         TRequestStatus* aStatusConsumed, const TRegion* aRegion)
sl@0
  1544
    {
sl@0
  1545
    NFLOG(("### ENTER * CSurfaceStream::SetAllNotifications()"));
sl@0
  1546
    TInt32 eventsToProcess = 0;
sl@0
  1547
    // let's take in evidence the events we have to process
sl@0
  1548
    
sl@0
  1549
    TNewGlobalNotifications newGlobalNotifications;
sl@0
  1550
    TInt idx = 0;
sl@0
  1551
    
sl@0
  1552
    if (aStatusConsumed && iNumberOfScreenAttachedAvailableNotif > 0)
sl@0
  1553
        {
sl@0
  1554
        if ((idx = AddNewGlobalNotification(aStatusConsumed, iNumberOfScreenAttachedAvailableNotif)) != KInvalidIndex)
sl@0
  1555
            {
sl@0
  1556
            newGlobalNotifications.iNewAvailableIdx = idx;
sl@0
  1557
            eventsToProcess |= ESOWF_EventAvailable;
sl@0
  1558
            }
sl@0
  1559
        }
sl@0
  1560
    
sl@0
  1561
    if (aStatusDisplayed && iNumberOfScreenAttachedDisplayedNotif > 0)
sl@0
  1562
        {
sl@0
  1563
        if ((idx = AddNewGlobalNotification(aStatusDisplayed, iNumberOfScreenAttachedDisplayedNotif)) != KInvalidIndex)
sl@0
  1564
            {
sl@0
  1565
            newGlobalNotifications.iNewDisplayedIdx = idx;
sl@0
  1566
            eventsToProcess |= ESOWF_EventDisplayed;
sl@0
  1567
            }
sl@0
  1568
        }
sl@0
  1569
    
sl@0
  1570
    if (aStatusDispXTimes && iNumberOfScreenAttachedDisplayedXNotif > 0)
sl@0
  1571
        {
sl@0
  1572
        if ((idx = AddNewGlobalNotification(aStatusDispXTimes, iNumberOfScreenAttachedDisplayedXNotif)) != KInvalidIndex)
sl@0
  1573
            {
sl@0
  1574
            newGlobalNotifications.iNewDisplayedXIdx = idx;
sl@0
  1575
            eventsToProcess |= ESOWF_EventDisplayedX;
sl@0
  1576
            }
sl@0
  1577
        }
sl@0
  1578
    
sl@0
  1579
    NFLOG(("### CSurfaceStream::SetAllNotifications eventsToProcess(0x%x)", eventsToProcess));
sl@0
  1580
    
sl@0
  1581
    idx = iCallBacks.Count();
sl@0
  1582
    TInt prevScreenNumber = KNoAssociatedScreenNumber;
sl@0
  1583
    TInt screenNumber = KNoAssociatedScreenNumber;
sl@0
  1584
    idx = iCallBacks.Count();
sl@0
  1585
    while (idx--)
sl@0
  1586
        {
sl@0
  1587
        if (iCallBacks[idx].iCallBackClientParam &&
sl@0
  1588
            (iCallBacks[idx].iEventMask == ESOWF_EventUpdated) &&
sl@0
  1589
            ((screenNumber = iCallBacks[idx].iScreenNumber) != KNoAssociatedScreenNumber) 
sl@0
  1590
            && prevScreenNumber != screenNumber)
sl@0
  1591
            {
sl@0
  1592
            NFLOG(("### CSurfaceStream::SetAllNotifications update composer %d", screenNumber));
sl@0
  1593
            SetNotifications(aBuffer,
sl@0
  1594
                             aStatusDisplayed, aTimeStamp,
sl@0
  1595
                             aStatusDispXTimes, aDisplayedXTimes,
sl@0
  1596
                             aStatusConsumed, aRegion, screenNumber, newGlobalNotifications);
sl@0
  1597
            
sl@0
  1598
            prevScreenNumber = screenNumber;
sl@0
  1599
            }
sl@0
  1600
        
sl@0
  1601
        }
sl@0
  1602
    
sl@0
  1603
    if (aStatusConsumed && !(eventsToProcess & ESOWF_EventAvailable))
sl@0
  1604
        {
sl@0
  1605
        User::RequestComplete(aStatusConsumed, KErrCancel);
sl@0
  1606
        }
sl@0
  1607
    
sl@0
  1608
    if (aStatusDisplayed && !(eventsToProcess & ESOWF_EventDisplayed))
sl@0
  1609
        {
sl@0
  1610
        *aTimeStamp = 0;
sl@0
  1611
        User::RequestComplete(aStatusDisplayed, KErrCancel);
sl@0
  1612
        }
sl@0
  1613
    
sl@0
  1614
    if (aStatusDispXTimes && !(eventsToProcess & ESOWF_EventDisplayedX))
sl@0
  1615
        {
sl@0
  1616
        User::RequestComplete(aStatusDispXTimes, KErrCancel);
sl@0
  1617
        }
sl@0
  1618
    NFLOG(("### EXIT * CSurfaceStream::SetAllNotifications()"));
sl@0
  1619
        
sl@0
  1620
    }
sl@0
  1621
sl@0
  1622
void CSurfaceStream::ProcessNotifications(TInt32 aEvent, 
sl@0
  1623
                                          TInt32 aScreenNumber, 
sl@0
  1624
                                          TInt32 aOperation, 
sl@0
  1625
                                          TInt32 aSerialNumber, 
sl@0
  1626
                                          TInt32* aReturnMask)
sl@0
  1627
    {
sl@0
  1628
    Guard g(iRefCountMutex);
sl@0
  1629
    NFLOG(("### ENTER CSurfaceStream::ProcessNotifications()"));
sl@0
  1630
    
sl@0
  1631
    TInt32 eventsToFind = aEvent & ESOWF_SUSEventsMask;
sl@0
  1632
    TInt idx = iCallBacks.Count();
sl@0
  1633
    while(idx-- && eventsToFind)
sl@0
  1634
        {
sl@0
  1635
        TInt32 currentEvent = iCallBacks[idx].iEventMask;
sl@0
  1636
        if (currentEvent & aEvent)
sl@0
  1637
            {
sl@0
  1638
            TNotificationBase* notifBase = (TNotificationBase*) iCallBacks[idx].iCallBackClientParam;
sl@0
  1639
            if (notifBase && notifBase->iStatus && iCallBacks[idx].iScreenNumber == aScreenNumber)
sl@0
  1640
                {
sl@0
  1641
                TInt callBackOperation = (aOperation == EDefaultOperation) ? currentEvent : ESOWF_ObserverCheckVisible;
sl@0
  1642
                eventsToFind &= ~currentEvent;
sl@0
  1643
                switch (currentEvent)
sl@0
  1644
                    {
sl@0
  1645
                    case ESOWF_EventAvailable:
sl@0
  1646
                        Available(callBackOperation, aSerialNumber, NULL, iCallBacks[idx].iCallBackClientParam, aReturnMask);
sl@0
  1647
                        break;
sl@0
  1648
                        
sl@0
  1649
                    case ESOWF_EventDisplayed:
sl@0
  1650
                        Displayed(callBackOperation, aSerialNumber, NULL, iCallBacks[idx].iCallBackClientParam, aReturnMask);
sl@0
  1651
                        break;
sl@0
  1652
                        
sl@0
  1653
                    case ESOWF_EventDisplayedX:
sl@0
  1654
                        DisplayedXTimes(callBackOperation, aSerialNumber, NULL, iCallBacks[idx].iCallBackClientParam, aReturnMask);
sl@0
  1655
                        break;
sl@0
  1656
                        
sl@0
  1657
                    default:
sl@0
  1658
                        break;
sl@0
  1659
                    }
sl@0
  1660
                }
sl@0
  1661
            }
sl@0
  1662
        }
sl@0
  1663
    NFLOG(("### EXIT CSurfaceStream::ProcessNotifications()"));
sl@0
  1664
    }
sl@0
  1665
sl@0
  1666
TInt CSurfaceStream::CheckBufferNumber(TInt aBuffer,
sl@0
  1667
                                       TRequestStatus* aStatusDisplayed,
sl@0
  1668
                                       TRequestStatus* aStatusDispXTimes,
sl@0
  1669
                                       TRequestStatus* aStatusConsumed)
sl@0
  1670
    {
sl@0
  1671
    if (aBuffer < 0 || aBuffer >= iInfo.iBuffers)
sl@0
  1672
        {
sl@0
  1673
            if (aStatusConsumed)
sl@0
  1674
                {
sl@0
  1675
                User::RequestComplete(aStatusConsumed, KErrArgument);
sl@0
  1676
                }
sl@0
  1677
            if (aStatusDisplayed)
sl@0
  1678
                {
sl@0
  1679
                User::RequestComplete(aStatusDisplayed, KErrArgument);
sl@0
  1680
                }
sl@0
  1681
            if (aStatusDispXTimes)
sl@0
  1682
                {
sl@0
  1683
                User::RequestComplete(aStatusDispXTimes, KErrArgument);
sl@0
  1684
                }
sl@0
  1685
            return KErrArgument;
sl@0
  1686
        }
sl@0
  1687
    else
sl@0
  1688
        {
sl@0
  1689
        return KErrNone;
sl@0
  1690
        }
sl@0
  1691
    }
sl@0
  1692
sl@0
  1693
void CSurfaceStream::Available(TInt32 aEvent, 
sl@0
  1694
                               TInt32 aSerialNumber, 
sl@0
  1695
                               ContentUpdatedParams* aParams, 
sl@0
  1696
                               void* aCallBackData, 
sl@0
  1697
                               TInt32* aReturnMask)
sl@0
  1698
    {
sl@0
  1699
    (void) aReturnMask;
sl@0
  1700
    NFLOG(("### ENTER CSurfaceStream::Available aEvent(0x%x) aSerialNumber(0x%x) "
sl@0
  1701
            "aParams(0x%x) aCallBackData(0x%x) aReturnMask(0x%x)", 
sl@0
  1702
            aEvent, aSerialNumber, aParams, aCallBackData, aReturnMask));
sl@0
  1703
    
sl@0
  1704
    TNotificationAvailable* callBackData = (TNotificationAvailable*) aCallBackData;
sl@0
  1705
    if (!callBackData)
sl@0
  1706
        {
sl@0
  1707
        return;
sl@0
  1708
        }
sl@0
  1709
    
sl@0
  1710
    switch(aEvent)
sl@0
  1711
        {
sl@0
  1712
        case ESOWF_ObserverProcessing:
sl@0
  1713
            NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing"));
sl@0
  1714
            // when a new available notification request is issued by SUS, we have to:
sl@0
  1715
            // 1. Overflow the old request status (GCE behaviour)
sl@0
  1716
            // 2. Update the observer
sl@0
  1717
            // 3. If immediate availabilty chec if the old request status can be completed
sl@0
  1718
            // 4. Inform the composer about any active available notifications requests
sl@0
  1719
            {
sl@0
  1720
            if (aParams)
sl@0
  1721
                {
sl@0
  1722
                // let's check first for overflow conditions
sl@0
  1723
                // and overflow the oldest if exists (GCE behaviour)
sl@0
  1724
                if (callBackData->iStatus)
sl@0
  1725
                    {
sl@0
  1726
                    NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing Overflow"));
sl@0
  1727
                    // oldest notifications is overflowed (like GCE behaviour)
sl@0
  1728
                    RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrOverflow);
sl@0
  1729
                    callBackData->iStatus = NULL;
sl@0
  1730
                    callBackData->iThreadId = 0;
sl@0
  1731
                    callBackData->iBufferNumber = -1;
sl@0
  1732
                    }
sl@0
  1733
                
sl@0
  1734
                // propagate the new data
sl@0
  1735
                callBackData->iSerialNumber = aSerialNumber;
sl@0
  1736
                TBool multibuffered = iInfo.iBuffers > 1;
sl@0
  1737
                if (multibuffered)
sl@0
  1738
                    {
sl@0
  1739
                    callBackData->iStatus = callBackData->iNewStatus;
sl@0
  1740
                    callBackData->iThreadId = callBackData->iNewThreadId;
sl@0
  1741
                    callBackData->iBufferNumber = callBackData->iNewBufferNumber;
sl@0
  1742
                    callBackData->iGlobalIndex = callBackData->iNewGlobalIndex;
sl@0
  1743
                    }
sl@0
  1744
                else
sl@0
  1745
                    {
sl@0
  1746
                    callBackData->iStatus = aParams->iStatusConsumed;
sl@0
  1747
                    callBackData->iThreadId = RThread().Id();
sl@0
  1748
                    callBackData->iBufferNumber = aParams->iBuffer;
sl@0
  1749
                    callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewAvailableIdx;
sl@0
  1750
                    }
sl@0
  1751
                 
sl@0
  1752
                // the availability can be immediately completed if the
sl@0
  1753
                // visibility status is known and the composer is not composing at that momment
sl@0
  1754
                if (callBackData->iStatus && aParams->iImmediateAvailable)
sl@0
  1755
                    {
sl@0
  1756
                    NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing Immediate Available"));
sl@0
  1757
                    if (iAcquiredWriteBuffer != WFC_INVALID_HANDLE)
sl@0
  1758
                        {
sl@0
  1759
                        iAcquiredWriteBuffer = BUFFER_WRITE_UPDATE_OVERWRITE;
sl@0
  1760
                        }
sl@0
  1761
                    
sl@0
  1762
                    SetReadBufferIndex(aParams->iBuffer);
sl@0
  1763
                    // immediate notification is possible because the context
sl@0
  1764
                    // is not composing at this momment
sl@0
  1765
                    if (aParams->iImmediateVisibility == SYM_CONTENT_NOT_VISIBLE)
sl@0
  1766
                        {
sl@0
  1767
                        RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNotVisible);
sl@0
  1768
                        }
sl@0
  1769
                    else
sl@0
  1770
                        {
sl@0
  1771
                        RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNone);
sl@0
  1772
                        }
sl@0
  1773
                    ResetCallBackData(callBackData, aEvent);
sl@0
  1774
                    }
sl@0
  1775
                    
sl@0
  1776
                if (multibuffered)
sl@0
  1777
                    {
sl@0
  1778
                    callBackData->iNewStatus = aParams->iStatusConsumed;
sl@0
  1779
                    callBackData->iNewThreadId = RThread().Id();
sl@0
  1780
                    callBackData->iNewBufferNumber = aParams->iBuffer;
sl@0
  1781
                    callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewAvailableIdx;
sl@0
  1782
                    }
sl@0
  1783
                
sl@0
  1784
                // let the composer know that the Availability has to be analysed further
sl@0
  1785
                if (aReturnMask && callBackData->iStatus)
sl@0
  1786
                    {
sl@0
  1787
                    NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing *aReturnMask |= ESOWF_EventAvailable"));
sl@0
  1788
                    *aReturnMask |= ESOWF_EventAvailable;
sl@0
  1789
                    }
sl@0
  1790
                }
sl@0
  1791
            }
sl@0
  1792
            break;
sl@0
  1793
sl@0
  1794
        case ESOWF_EventAvailable:
sl@0
  1795
            NFLOG(("###CSurfaceStream::Available ESOWF_EventAvailable"));
sl@0
  1796
            if (callBackData->iStatus)
sl@0
  1797
                {
sl@0
  1798
                // if it is an event just added during composition, we wxpect the same serial number
sl@0
  1799
                RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNone);
sl@0
  1800
                // clean the old reques notification related info
sl@0
  1801
                callBackData->iSerialNumber = aSerialNumber;
sl@0
  1802
                callBackData->iStatus = NULL;
sl@0
  1803
                callBackData->iThreadId = 0;
sl@0
  1804
                callBackData->iBufferNumber = -1;
sl@0
  1805
                }
sl@0
  1806
            break;
sl@0
  1807
            
sl@0
  1808
        case ESOWF_ObserverCheckVisible:
sl@0
  1809
            NFLOG(("###CSurfaceStream::Available ESOWF_ObserverCheckVisible"));
sl@0
  1810
            if (callBackData->iStatus)
sl@0
  1811
                {
sl@0
  1812
                // complete the old request status (standard GCE behaviour)
sl@0
  1813
                RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNotVisible);
sl@0
  1814
                // clean the old reques notification related info
sl@0
  1815
                callBackData->iSerialNumber = aSerialNumber;
sl@0
  1816
                callBackData->iStatus = NULL;
sl@0
  1817
                callBackData->iThreadId = 0;
sl@0
  1818
                callBackData->iBufferNumber = -1;
sl@0
  1819
                }
sl@0
  1820
            break;
sl@0
  1821
            
sl@0
  1822
        case ESOWF_ObserverCancel:
sl@0
  1823
            {
sl@0
  1824
            NFLOG(("###CSurfaceStream::Available ESOWF_ObserverCancel"));
sl@0
  1825
            // cancel both requests if they are valid
sl@0
  1826
            RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrCancel);
sl@0
  1827
            RequestComplete(callBackData->iNewThreadId, callBackData->iNewStatus, callBackData->iGlobalIndex, KErrCancel);
sl@0
  1828
            ResetCallBackData(callBackData, aEvent);
sl@0
  1829
            }
sl@0
  1830
            break;
sl@0
  1831
            
sl@0
  1832
        default:
sl@0
  1833
            return;
sl@0
  1834
        }
sl@0
  1835
    NFLOG(("EXIT ###CSurfaceStream::Available()"));
sl@0
  1836
    }
sl@0
  1837
sl@0
  1838
sl@0
  1839
void CSurfaceStream::Displayed(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask)
sl@0
  1840
    {
sl@0
  1841
    TInt notification = KErrNone;
sl@0
  1842
    (void) aReturnMask;
sl@0
  1843
    NFLOG(("### ENTER CSurfaceStream::Displayed aEvent(0x%x) aSerialNumber(0x%x) "
sl@0
  1844
            "aParams(0x%x) aCallBackData(0x%x) aReturnMask(0x%x)", 
sl@0
  1845
            aEvent, aSerialNumber, aParams, aCallBackData, aReturnMask));
sl@0
  1846
    TNotificationDisplayed* callBackData = (TNotificationDisplayed*) aCallBackData;
sl@0
  1847
    if (!callBackData)
sl@0
  1848
        {
sl@0
  1849
        return;
sl@0
  1850
        }
sl@0
  1851
    
sl@0
  1852
    switch(aEvent)
sl@0
  1853
        {
sl@0
  1854
        case ESOWF_ObserverProcessing:
sl@0
  1855
            NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverProcessing"));
sl@0
  1856
            // When a new available notification request is issued by SUS, we have to:
sl@0
  1857
            // 1. Overflow the previous request status
sl@0
  1858
            // 2. Update the observer
sl@0
  1859
            // 3. Inform the composer about any active available notifications requests
sl@0
  1860
            
sl@0
  1861
            if (callBackData->iStatus)
sl@0
  1862
                {
sl@0
  1863
                NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverProcessing Overflowing"));
sl@0
  1864
                RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrOverflow);
sl@0
  1865
                ResetCallBackData(callBackData, aEvent);
sl@0
  1866
                }
sl@0
  1867
            if (aParams && aParams->iStatusDisplayed)
sl@0
  1868
                {
sl@0
  1869
                __ASSERT_DEBUG(aParams->iTimeStamp,
sl@0
  1870
                       (iRefCountMutex.Signal(),Panic(EOwfInvalidSUSDisplayedParameter)));
sl@0
  1871
                callBackData->iStatus = aParams->iStatusDisplayed;
sl@0
  1872
                callBackData->iThreadId = RThread().Id();
sl@0
  1873
                callBackData->iBufferNumber = aParams->iBuffer;
sl@0
  1874
                callBackData->iSerialNumber = aSerialNumber;
sl@0
  1875
                callBackData->iTimeStamp = aParams->iTimeStamp;
sl@0
  1876
                callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewDisplayedIdx;
sl@0
  1877
                NFLOG(("###CSurfaceStream::Displayed iGlobalIndex(%d)", callBackData->iGlobalIndex));
sl@0
  1878
                }
sl@0
  1879
            if (aReturnMask && callBackData->iStatus)
sl@0
  1880
                {
sl@0
  1881
                NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverProcessing *aReturnMask |= ESOWF_EventDisplayed"));
sl@0
  1882
                *aReturnMask |= ESOWF_EventDisplayed;
sl@0
  1883
                }
sl@0
  1884
            return;
sl@0
  1885
            
sl@0
  1886
        case ESOWF_EventDisplayed:
sl@0
  1887
            // this invoked by composer
sl@0
  1888
            NFLOG(("###CSurfaceStream::Displayed ESOWF_EventDisplayed"));
sl@0
  1889
            if (!callBackData->iStatus)
sl@0
  1890
                {
sl@0
  1891
                // no active notification, nothing to do
sl@0
  1892
                NFLOG(("###CSurfaceStream::Displayed ESOWF_EventDisplayed no active notifications"));
sl@0
  1893
                return;
sl@0
  1894
                }
sl@0
  1895
            // deffer for next composition the processing if the updated happended during a composition
sl@0
  1896
            if (callBackData->iSerialNumber == aSerialNumber && aReturnMask)
sl@0
  1897
                {
sl@0
  1898
                NFLOG(("###CSurfaceStream::Displayed ESOWF_EventDisplayed *aReturnMask |= ESOWF_EventDisplayed"));
sl@0
  1899
                *aReturnMask |= ESOWF_EventDisplayed;
sl@0
  1900
                return;
sl@0
  1901
                }
sl@0
  1902
            // complete the active request status
sl@0
  1903
            callBackData->iSerialNumber = aSerialNumber;
sl@0
  1904
            *callBackData->iTimeStamp = User::FastCounter();
sl@0
  1905
            notification = KErrNone;
sl@0
  1906
            break;
sl@0
  1907
sl@0
  1908
        case ESOWF_ObserverCheckVisible:
sl@0
  1909
            // visibility check comming from composer
sl@0
  1910
            NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverCheckVisible"));
sl@0
  1911
            if (!callBackData->iStatus)
sl@0
  1912
                {
sl@0
  1913
                // deffer for next composition the processing if the updated happended during a composition
sl@0
  1914
                // or if no active notification, nothing to do
sl@0
  1915
                NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverCheckVisible = Not Visible"));
sl@0
  1916
                return;
sl@0
  1917
                }
sl@0
  1918
            notification = KErrNotVisible;
sl@0
  1919
            callBackData->iSerialNumber = aSerialNumber;
sl@0
  1920
            break;
sl@0
  1921
            
sl@0
  1922
        case ESOWF_ObserverCancel:
sl@0
  1923
            // cancel the active notification
sl@0
  1924
            NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverCancel"));
sl@0
  1925
            if (!callBackData->iStatus)
sl@0
  1926
                {
sl@0
  1927
                return;
sl@0
  1928
                }
sl@0
  1929
            notification = KErrCancel;
sl@0
  1930
            break;
sl@0
  1931
            
sl@0
  1932
        default:
sl@0
  1933
            return;
sl@0
  1934
        }
sl@0
  1935
    
sl@0
  1936
    RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, notification);
sl@0
  1937
    ResetCallBackData(callBackData, aEvent);
sl@0
  1938
    NFLOG(("EXIT ###CSurfaceStream::Displayed()"));
sl@0
  1939
    }
sl@0
  1940
sl@0
  1941
void CSurfaceStream::DisplayedXTimes(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask)
sl@0
  1942
    {
sl@0
  1943
    TInt notification = KErrNone;
sl@0
  1944
    
sl@0
  1945
    NFLOG(("### ENTER CSurfaceStream::DisplayedXTimes aEvent(0x%x) aSerialNumber(0x%x) "
sl@0
  1946
            "aParams(0x%x) aCallBackData(0x%x) aReturnMask(0x%x)", 
sl@0
  1947
            aEvent, aSerialNumber, aParams, aCallBackData, aReturnMask));
sl@0
  1948
    
sl@0
  1949
    TNotificationDisplayedX* callBackData = (TNotificationDisplayedX*) aCallBackData;
sl@0
  1950
    if (!callBackData)
sl@0
  1951
        {
sl@0
  1952
        return;
sl@0
  1953
        }
sl@0
  1954
sl@0
  1955
    switch(aEvent)
sl@0
  1956
        {
sl@0
  1957
        case ESOWF_ObserverProcessing:
sl@0
  1958
            // When a new available notification request is issued by SUS, we have to:
sl@0
  1959
            // 1. Overflow the previous request status
sl@0
  1960
            // 2. Update the observer
sl@0
  1961
            // 3. Inform the composer about any active available notifications requests
sl@0
  1962
            NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverProcessing"));
sl@0
  1963
            if (callBackData->iStatus)
sl@0
  1964
                {
sl@0
  1965
                NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverProcessing Overflowing"));
sl@0
  1966
                RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrOverflow);
sl@0
  1967
                ResetCallBackData(callBackData, aEvent);
sl@0
  1968
                }
sl@0
  1969
            if (aParams && aParams->iStatusDispXTimes)
sl@0
  1970
                {
sl@0
  1971
                __ASSERT_DEBUG(aParams->iDisplayedXTimes && *aParams->iDisplayedXTimes >= 1,
sl@0
  1972
                       (iRefCountMutex.Signal(),Panic(EOwfInvalidSUSDisplayedXTimesParameter)));
sl@0
  1973
                callBackData->iStatus = aParams->iStatusDispXTimes;
sl@0
  1974
                callBackData->iThreadId = RThread().Id();
sl@0
  1975
                callBackData->iBufferNumber = aParams->iBuffer;
sl@0
  1976
                callBackData->iSerialNumber = aSerialNumber;
sl@0
  1977
                callBackData->iCount = *aParams->iDisplayedXTimes;
sl@0
  1978
                callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewDisplayedXIdx;
sl@0
  1979
                }
sl@0
  1980
            
sl@0
  1981
            if (aReturnMask && callBackData->iStatus)
sl@0
  1982
                {
sl@0
  1983
                NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverProcessing *aReturnMask |= ESOWF_EventDisplayedX"));
sl@0
  1984
                *aReturnMask |= ESOWF_EventDisplayedX;
sl@0
  1985
                }
sl@0
  1986
            return;
sl@0
  1987
            
sl@0
  1988
        case ESOWF_EventDisplayedX:
sl@0
  1989
            NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX"));
sl@0
  1990
            if (!callBackData->iStatus)
sl@0
  1991
                {
sl@0
  1992
                // no active notification, nothing to do
sl@0
  1993
                return;
sl@0
  1994
                }
sl@0
  1995
            
sl@0
  1996
            // deffer for next composition the processing if the updated happended during a composition
sl@0
  1997
            if (callBackData->iSerialNumber == aSerialNumber)
sl@0
  1998
                {
sl@0
  1999
                if (aReturnMask)
sl@0
  2000
                    {
sl@0
  2001
                    NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX *aReturnMask |= ESOWF_EventDisplayedX"));
sl@0
  2002
                    *aReturnMask |= ESOWF_EventDisplayedX;
sl@0
  2003
                    }
sl@0
  2004
                return;
sl@0
  2005
                }
sl@0
  2006
            
sl@0
  2007
            callBackData->iSerialNumber = aSerialNumber;
sl@0
  2008
            
sl@0
  2009
            // complete the active request status
sl@0
  2010
            if (callBackData->iCount > 1)
sl@0
  2011
                {
sl@0
  2012
                // inform the composer a new notification is needed
sl@0
  2013
                callBackData->iCount--;
sl@0
  2014
                if (aReturnMask)
sl@0
  2015
                    {
sl@0
  2016
                    NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX *aReturnMask |= ESOWF_EventDisplayedX iCount(%d)", callBackData->iCount));
sl@0
  2017
                    *aReturnMask |= ESOWF_EventDisplayedX;
sl@0
  2018
                    }
sl@0
  2019
                return;
sl@0
  2020
                }
sl@0
  2021
            
sl@0
  2022
            NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX iCount(%d)", callBackData->iCount));
sl@0
  2023
            notification = KErrNone;
sl@0
  2024
            break;
sl@0
  2025
sl@0
  2026
        case ESOWF_ObserverCheckVisible:
sl@0
  2027
            NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverCheckVisible"));
sl@0
  2028
            // visibility check comming from composer
sl@0
  2029
            if (!callBackData->iStatus || 
sl@0
  2030
                callBackData->iSerialNumber == aSerialNumber)
sl@0
  2031
                {
sl@0
  2032
                // deffer for next composition the processing if the updated happended during a composition
sl@0
  2033
                // or if no active notification, nothing to do
sl@0
  2034
                return;
sl@0
  2035
                }
sl@0
  2036
            callBackData->iSerialNumber = aSerialNumber;
sl@0
  2037
            notification = KErrNotVisible;
sl@0
  2038
            break;
sl@0
  2039
            
sl@0
  2040
        case ESOWF_ObserverCancel:
sl@0
  2041
            // cancel the active notification
sl@0
  2042
            NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverCancel"));
sl@0
  2043
            if (!callBackData->iStatus)
sl@0
  2044
                {
sl@0
  2045
                return;
sl@0
  2046
                }
sl@0
  2047
            notification = KErrCancel;
sl@0
  2048
            break;
sl@0
  2049
            
sl@0
  2050
        default:
sl@0
  2051
            return;
sl@0
  2052
        }
sl@0
  2053
    
sl@0
  2054
    RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, notification);
sl@0
  2055
    ResetCallBackData(callBackData, aEvent);
sl@0
  2056
    NFLOG(("EXIT ###CSurfaceStream::DisplayedXTimes()"));
sl@0
  2057
    }
sl@0
  2058
sl@0
  2059
void CSurfaceStream::ResetCallBackData(void* aCallBackData,
sl@0
  2060
                                       TInt32 aEvent)
sl@0
  2061
    {
sl@0
  2062
    switch (aEvent)
sl@0
  2063
        {
sl@0
  2064
        case ESOWF_EventAvailable:
sl@0
  2065
            {
sl@0
  2066
            TNotificationAvailable* available = (TNotificationAvailable*) aCallBackData;
sl@0
  2067
            available->iStatus = NULL;
sl@0
  2068
            available->iThreadId = 0;
sl@0
  2069
            available->iBufferNumber = -1;
sl@0
  2070
            available->iGlobalIndex = KInvalidIndex;
sl@0
  2071
            available->iNewBufferNumber = -1;
sl@0
  2072
            available->iNewStatus = NULL;
sl@0
  2073
            available->iNewThreadId = 0;
sl@0
  2074
            available->iNewGlobalIndex = KInvalidIndex;
sl@0
  2075
            }
sl@0
  2076
            break;
sl@0
  2077
            
sl@0
  2078
        case ESOWF_EventDisplayed:
sl@0
  2079
            {
sl@0
  2080
            TNotificationDisplayed* displayed = (TNotificationDisplayed*) aCallBackData; 
sl@0
  2081
            displayed->iStatus = NULL;
sl@0
  2082
            displayed->iThreadId = 0;
sl@0
  2083
            displayed->iBufferNumber = -1;
sl@0
  2084
            displayed->iTimeStamp = NULL;
sl@0
  2085
            displayed->iGlobalIndex = KInvalidIndex;
sl@0
  2086
            }
sl@0
  2087
            break;
sl@0
  2088
            
sl@0
  2089
        case ESOWF_EventDisplayedX:
sl@0
  2090
            {
sl@0
  2091
            TNotificationDisplayedX* displayed = (TNotificationDisplayedX*) aCallBackData; 
sl@0
  2092
            displayed->iStatus = NULL;
sl@0
  2093
            displayed->iThreadId = 0;
sl@0
  2094
            displayed->iBufferNumber = -1;
sl@0
  2095
            displayed->iCount = 0;
sl@0
  2096
            displayed->iGlobalIndex = KInvalidIndex;
sl@0
  2097
            }
sl@0
  2098
            break;
sl@0
  2099
            
sl@0
  2100
        default:
sl@0
  2101
            break;
sl@0
  2102
        }
sl@0
  2103
    }
sl@0
  2104
sl@0
  2105
void CSurfaceStream::CancelNotifications()
sl@0
  2106
    {
sl@0
  2107
    NFLOG(("ENTER ###CSurfaceStream::CancelNotifications()"));
sl@0
  2108
    TInt cancelEvents = ESOWF_AllEventsMask;
sl@0
  2109
    RemoveObserver(cancelEvents, NULL);
sl@0
  2110
    NFLOG(("EXIT ###CSurfaceStream::CancelNotifications()"));
sl@0
  2111
    }
sl@0
  2112
sl@0
  2113
TInt CSurfaceStream::Stride(TInt aWidth, TUidPixelFormat aPixelFormat)
sl@0
  2114
    {
sl@0
  2115
    
sl@0
  2116
    TInt bytesPerPixel = BytesPerPixel(aPixelFormat);
sl@0
  2117
    
sl@0
  2118
    if (bytesPerPixel >= 0)
sl@0
  2119
        {
sl@0
  2120
         return bytesPerPixel * aWidth;  // number of bytes between start of one line and start of next  
sl@0
  2121
        }
sl@0
  2122
    else
sl@0
  2123
        {
sl@0
  2124
        return (aWidth-(bytesPerPixel+1)) / (-bytesPerPixel);
sl@0
  2125
        }
sl@0
  2126
    }
sl@0
  2127
sl@0
  2128
void CSurfaceStream::SetFlipState(TBool aFlip)
sl@0
  2129
    {
sl@0
  2130
    Guard g1(iRefCountMutex);
sl@0
  2131
    if (aFlip)
sl@0
  2132
        {
sl@0
  2133
        iNewFlip = EFlippedTargetFlipped;
sl@0
  2134
        }
sl@0
  2135
    else
sl@0
  2136
        {
sl@0
  2137
        iNewFlip = EFlippedTargetNormal;
sl@0
  2138
        }
sl@0
  2139
    }
sl@0
  2140
sl@0
  2141
TInt CSurfaceStream::GetChunkHandle()
sl@0
  2142
    {
sl@0
  2143
    return iBufferChunk.Handle();
sl@0
  2144
    }