First public contribution.
1 // Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
15 // CSurfaceStream implementation
18 #include <graphics/suerror.h>
19 #include <graphics/surfacetypes.h>
21 #include "surfacestream.h"
22 #include "openwfcpanic.h"
23 #include "streammap.h"
24 #include "symbianstream.h"
25 #define WFC_INVALID_HANDLE NULL
27 const TInt KInvalidIndex = KNoAssociatedScreenNumber;
29 struct CSurfaceStream::TCallBackEntry
31 typedef SymbianStreamCallback TSimpleCallback;
34 TSimpleCallback iCallBackFunction;
35 TAny* iCallBackClientParam;
40 CSurfaceStream::TCallBackEntry::TCallBackEntry():
41 iCallBackFunction(NULL),
42 iCallBackClientParam(NULL),
43 iEventMask(ESOWF_NoEvent),
44 iScreenNumber(KNoAssociatedScreenNumber)
48 void CSurfaceStream::TCallBackEntry::Reset()
50 iCallBackFunction = NULL;
51 iCallBackClientParam = NULL;
52 iEventMask = ESOWF_NoEvent;
53 iScreenNumber = KNoAssociatedScreenNumber;
56 struct CSurfaceStream::TGlobalNotification
58 TGlobalNotification();
60 TRequestStatus* iStatus;
62 TInt iPendingNotifications;
63 TInt iCompletedOkNotifications;
64 TInt iCanceledNotifications;
65 TInt iOverflowedNotifications;
66 TInt iNotVisibleNotifications;
67 TInt iOtherNotifications;
71 CSurfaceStream::TGlobalNotification::TGlobalNotification():
74 iPendingNotifications(0),
75 iCompletedOkNotifications(0),
76 iCanceledNotifications(0),
77 iOverflowedNotifications(0),
78 iNotVisibleNotifications(0),
79 iOtherNotifications(0)
84 void CSurfaceStream::TGlobalNotification::Reset()
88 iPendingNotifications = 0;
89 iCompletedOkNotifications = 0;
90 iCanceledNotifications = 0;
91 iOverflowedNotifications = 0;
92 iNotVisibleNotifications = 0;
93 iOtherNotifications = 0;
96 struct CSurfaceStream::TNewGlobalNotifications
98 TNewGlobalNotifications();
99 TInt iNewAvailableIdx;
100 TInt iNewDisplayedIdx;
101 TInt iNewDisplayedXIdx;
104 CSurfaceStream::TNewGlobalNotifications::TNewGlobalNotifications():
105 iNewAvailableIdx(KInvalidIndex),
106 iNewDisplayedIdx(KInvalidIndex),
107 iNewDisplayedXIdx(KInvalidIndex)
111 CSurfaceStream::Guard::Guard(RFastLock& aLock):
117 CSurfaceStream::Guard::~Guard()
122 CSurfaceStream::CSurfaceStream():
123 iSurfaceId(TSurfaceId::CreateNullId()),
126 iNumberOfScreenAttachedAvailableNotif(0),
127 iNumberOfScreenAttachedDisplayedNotif(0),
128 iNumberOfScreenAttachedDisplayedXNotif(),
129 iFlipState(EFlippedTargetNormal),
130 iNewFlip(EFlipNotSet)
132 iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::EObjectRefField]=
133 reinterpret_cast<TInt>(this);
134 iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::ETypeClassField]=
135 TSurfaceId::EStreamHandle<<TSurfaceId::TSurfaceUsage::ETypeClassShift;
138 CSurfaceStream::ContentUpdatedParams::ContentUpdatedParams(TInt aBuffer,
139 TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
140 TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
141 TRequestStatus* aStatusConsumed, const TRegion* aRegion,
142 TBool aImmediateAvailable, TInt32 aImmediateVisibility,
143 const TNewGlobalNotifications& aGlobalNotifications):
145 iStatusDisplayed(aStatusDisplayed),
146 iTimeStamp(aTimeStamp),
147 iStatusDispXTimes(aStatusDispXTimes),
148 iDisplayedXTimes(aDisplayedXTimes),
149 iStatusConsumed(aStatusConsumed),
151 iImmediateAvailable(aImmediateAvailable),
152 iImmediateVisibility(aImmediateVisibility),
153 iGlobalNotifications(aGlobalNotifications)
158 CSurfaceStream::~CSurfaceStream()
160 // Cancel any outstanding notifications
161 CancelNotifications();
163 iGlobalNotifications.Close();
164 iBufferChunk.Close();
166 if (!iSurfaceId.IsNull() && iSurfaceId.Type() == TSurfaceTypes::ESurfaceManagerSurface)
168 TRAP_IGNORE(GetSingletonL().SurfaceManager().CloseSurface(iSurfaceId));
171 iRefCountMutex.Close();
172 iCallBacksMutex.Close();
173 delete [] iBufferInfo;
176 CSurfaceStream* CSurfaceStream::NewLC(const TSurfaceId& aId)
178 CSurfaceStream* self = new (ELeave)CSurfaceStream();
179 CleanupStack::PushL(self);
180 self->ConstructL(aId);
184 void CSurfaceStream::ConstructL(const TSurfaceId& aId)
186 User::LeaveIfError(iRefCountMutex.CreateLocal());
187 User::LeaveIfError(iCallBacksMutex.CreateLocal());
189 RSurfaceManager::TInfoBuf infoBuf;
190 SurfaceInfoL(aId, infoBuf);
193 COpenWfcStreamMap& stream = GetSingletonL();
194 //Create array for TBufferInfo
195 iBufferInfo = new(ELeave) TBufferInfo[iInfo.iBuffers];
196 for(TInt i = 0; i < iInfo.iBuffers; i++)
201 case TSurfaceTypes::ESurfaceManagerSurface:
203 User::LeaveIfError(stream.SurfaceManager().GetBufferOffset(iSurfaceId,
207 case TSurfaceId::EScreenSurface:
209 TInt screenId = SurfaceId().iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField];
210 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayOffsetToFirstPixel, offset));
214 User::Leave(KErrNotSupported);
217 iBufferInfo[i].iRefCount = 0;
218 iBufferInfo[i].iOffset = offset;
222 void CSurfaceStream::SurfaceInfoL(const TSurfaceId& aId, RSurfaceManager::TInfoBuf& aInfoBuf)
224 COpenWfcStreamMap& stream = GetSingletonL();
227 case TSurfaceTypes::ESurfaceManagerSurface:
229 iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::EObjectRefField]=
230 reinterpret_cast<TInt>(this);
231 iStreamProxySurfaceId.iInternal[TSurfaceId::TSurfaceUsage::ETypeClassField]=
232 TSurfaceId::EStreamHandle<<TSurfaceId::TSurfaceUsage::ETypeClassShift;
234 User::LeaveIfError(stream.SurfaceManager().OpenSurface(aId));
236 User::LeaveIfError(stream.SurfaceManager().SurfaceInfo(iSurfaceId, aInfoBuf));
239 case TSurfaceId::EScreenSurface:
241 // DSA surface only has one buffer
242 aInfoBuf().iBuffers = 1;
244 TInt screenId = aId.iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField];
246 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayXPixels, width));
249 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayYPixels, height));
251 aInfoBuf().iSize = TSize(width, height);
254 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayBitsPerPixel, bpp));
256 TUidPixelFormat pixelFormat = static_cast<TUidPixelFormat> (aId.iInternal[TSurfaceId::TScreenSurfaceUsage::ETypeGuidField]);
259 //if (bpp==12 || bpp==4)) //This allows low-color indices to be semi-functionally tested
262 pixelFormat = EUidPixelFormatXRGB_4444;
266 pixelFormat = EUidPixelFormatRGB_565;
268 else if (bpp== 24 || bpp==32)
270 pixelFormat = EUidPixelFormatARGB_8888;
274 User::Leave(KErrNotSupported);
278 aInfoBuf().iPixelFormat = pixelFormat;
280 #ifdef SYMBIAN_ROTATION_MODE_CHANGES
281 TInt displayMode = aId.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
283 TInt displayMode = 0;
284 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayMode, displayMode));
287 #if defined(SYMBIAN_ROTATION_MODE_CHANGES)
288 if (displayMode & TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag) // 90 | 270 degree rotation
290 // Swap dimensions and recalculate stride. Assume no padding for now.
291 aInfoBuf().iSize.iWidth = height;
292 aInfoBuf().iSize.iHeight = width;
293 //"vertical" stride has already been fetched
295 #elif defined(SYMBIAN_ROTATION_CHANGES)
296 if (aSurface.iInternal[1] & (2 | 8)) // 90 | 270 degree rotation
298 // Swap dimensions and recalculate stride. Assume no padding for now.
299 aInfoBuf().iSize.iWidth = height;
300 aInfoBuf().iSize.iHeight = width;
301 aInfoBuf().iStride = infoBuf().iSize.width * bpp;
305 TInt stride = displayMode;
306 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayOffsetBetweenLines, stride));
308 aInfoBuf().iStride = stride;
314 User::Leave(KErrNotSupported);
318 COpenWfcStreamMap& CSurfaceStream::GetSingletonL()
320 return COpenWfcStreamMap::InstanceL();
324 Helper to resolve handle to stream object
327 CSurfaceStream* CSurfaceStream::FromHandle(SymbianStreamType aNativeStreamHandle)
329 if (aNativeStreamHandle)
331 if (aNativeStreamHandle->Type()==TSurfaceId::EStreamHandle)
333 return reinterpret_cast<CSurfaceStream*>(aNativeStreamHandle->iInternal[TSurfaceId::TSurfaceUsage::EObjectRefField]);
340 Helper to resolve handle to stream object
342 SymbianStreamType CSurfaceStream::ToHandle()
346 return &iStreamProxySurfaceId;
355 /** Returns internal surface ID.
357 * @return surface id asociated with this stream
359 const TSurfaceId& CSurfaceStream::SurfaceId()const
365 * \brief Increase stream's reference count by one.
368 void CSurfaceStream::AddReference()
370 iRefCountMutex.Wait();
372 iRefCountMutex.Signal();
379 * \brief Returns flag if reference count is now zero.
382 TBool CSurfaceStream::RemainingReference()
384 iRefCountMutex.Wait();
385 TBool countZero=iRefCount==0;
386 iRefCountMutex.Signal();
392 * \brief Decrease stream's reference count by one and destroy
393 * the stream, if the reference count goes to zero.
395 * All acquired read & write buffers must be released
396 * before calling WFC_Native_Destroy.
399 void CSurfaceStream::ReleaseReference()
401 iRefCountMutex.Wait();
405 // it is required to signal the mutex before calling LockDestroy()
406 iRefCountMutex.Signal();
407 TRAP_IGNORE(GetSingletonL().LockDestroy(this));
411 iRefCountMutex.Signal();
416 * \brief Get stream "frame header". Can be used to query
417 * all or some of the frame properties.
419 * \param width Pointer to location where width parameter should be saved
420 * \param height Pointer to location where height parameter should be saved
421 * \param stride Pointer to location where stride (row size in bytes)
422 * parameter should be saved
423 * \param pixelSize Pointer to location where pizelSize (pixel size in bytes) if the format has more than 8 bits.
424 * For the formats with fewer than 8 bits per pixel, or ones that do not use packed pixel
425 * the parameter is a negative number
426 * parameter should be saved
428 * Passing a NULL pointer implies that particular
429 * value is of no interest to caller. E.g.
430 * owfNativeStreamGetHeader(stream, &w, &h, NULL, NULL, NULL);
431 * would only fetch width & height parameters.
433 void CSurfaceStream::GetHeader( khronos_int32_t* aWidth,
434 khronos_int32_t* aHeight,
435 khronos_int32_t* aStride,
436 SymOwfPixelFormat* aFormat,
437 khronos_int32_t* aPixelSize)
439 Guard g1(iRefCountMutex);
442 if (iFlipState == EFlippedTargetFlipped)
444 *aWidth = static_cast<khronos_int32_t>(iInfo.iSize.iHeight);
448 *aWidth = static_cast<khronos_int32_t>(iInfo.iSize.iWidth);
454 if (iFlipState == EFlippedTargetFlipped)
456 *aHeight = static_cast<khronos_int32_t>(iInfo.iSize.iWidth);
460 *aHeight = static_cast<khronos_int32_t>(iInfo.iSize.iHeight);
465 if (iFlipState == EFlippedTargetFlipped)
467 *aStride = Stride(iInfo.iSize.iHeight, iInfo.iPixelFormat);
471 *aStride = static_cast<khronos_int32_t>(iInfo.iStride);
476 *aFormat=iInfo.iPixelFormat;
480 *aPixelSize = static_cast<khronos_int32_t>(BytesPerPixel(iInfo.iPixelFormat));
485 * \brief Acquires read buffer for stream. For > 1 buffer
486 * streams this function doesn't block, but simply returns
487 * WFC_INVALID_HANDLE if no buffer is available for reading.
488 * For 1 buffer stream the caller is blocked until the buffer
489 * is ready for reading (the reader has committed the buffer,
493 * \return WFC_INVALID_HANDLE if no buffer is available or
494 * handle to last committed buffer.
496 * An example sequence for 3 buffer stream where
497 * producer produces frames approx. after every ~5th time unit.
498 * Consumer consumes buffers at constant rate of 1buf/time unit.
499 * Pframe is the number/handle of buffer that is being written by
500 * the producer (let's assume that it takes 2 time units
501 * for producer to produce a frame/buffer.) Cframe is the number/
502 * handle of the buffer the consumer receives from AcquireReadBuffer().
503 * "i" stands for WFC_INVALID_HANDLE:
506 * Time: 0 5 10 15 20 25
507 * Pframe: 0 1 2 0 1 ...
508 * Cframe: ii00000111112222200000111...
511 SymbianStreamBuffer CSurfaceStream::AcquireReadBuffer()
513 SymbianStreamBuffer buffer = WFC_INVALID_HANDLE;
515 iRefCountMutex.Wait();
516 TInt index = GetReadBufferIndex();
517 buffer = IndexToReadHandle(index);
518 ++(iBufferInfo[index].iRefCount);
519 iRefCountMutex.Signal();
525 * \brief Releases read buffer.
527 * When read buffer is released, it is marked as clean to
528 * be written again, unless it is the only committed buffer
529 * in which case it is recycled so that the same buffer
530 * can be read again (as long as no new buffers are committed
533 * \param buf Buffer handle. Must be valid read buffer handle for
536 TInt CSurfaceStream::ReleaseReadBuffer(SymbianStreamBuffer aBuf)
538 TInt index = BufferHandleToIndex(aBuf);
539 if(index < 0 || index >= iInfo.iBuffers)
541 return KErrBadHandle;
544 iRefCountMutex.Wait();
546 __ASSERT_DEBUG(iBufferInfo[index].iRefCount > 0,
547 (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
549 --(iBufferInfo[index].iRefCount);
551 iRefCountMutex.Signal();
557 * \brief Acquires write buffer for stream.
559 * Returns handle to a buffer that can be used to write
560 * data into stream. If no clean buffer is available,
561 * invalid handle is returned.
564 * \return Handle to a writable buffer
566 SymbianStreamBuffer CSurfaceStream::AcquireWriteBuffer()
568 SymbianStreamBuffer buffer = WFC_INVALID_HANDLE;
570 iRefCountMutex.Wait();
571 TInt index = GetWriteBufferIndex();
572 //Writers are currently not blocked in single buffered,
573 //but if proper signalling was implemented then they could be blocked
574 //Ideally, make signalling/blocking a parameter flag of AcquireWriteBuffer
575 if (iInfo.iBuffers>1 && iBufferInfo[index].iRefCount > 0)
577 buffer = WFC_INVALID_HANDLE;
581 buffer = IndexToWriteHandle(index);
582 ++(iBufferInfo[index].iRefCount);
583 iAcquiredWriteBuffer = buffer;
585 iRefCountMutex.Signal();
594 * \brief Releases write buffer to stream.
595 * Released buffer is made new front buffer, i.e., producer is expected
596 * to release buffer is the same order they were acquired.
598 * \param buf Buffer handle. Must be valid write buffer handle
601 void CSurfaceStream::ReleaseWriteBuffer(SymbianStreamBuffer aBuf)
603 TInt index = BufferHandleToIndex(aBuf);
604 if(index < 0 || index >= iInfo.iBuffers)
609 iRefCountMutex.Wait();
611 __ASSERT_DEBUG(iBufferInfo[index].iRefCount > 0,
612 (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
614 __ASSERT_DEBUG((iAcquiredWriteBuffer == aBuf) || (iAcquiredWriteBuffer == BUFFER_WRITE_UPDATE_OVERWRITE),
615 (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
617 if (iAcquiredWriteBuffer != BUFFER_WRITE_UPDATE_OVERWRITE)
619 // Update read buffer to point to buffer just finished writing
620 SetReadBufferIndex(index);
622 iAcquiredWriteBuffer = WFC_INVALID_HANDLE;
624 --(iBufferInfo[index].iRefCount);
626 if (iNewFlip != EFlipNotSet)
628 iFlipState = iNewFlip;
629 iNewFlip = EFlipNotSet;
632 iRefCountMutex.Signal();
634 NotifyObservers(ESOWF_EventComposed);
635 ReleaseReference(); //Note this means this NotifyObservers can never get the rug pulled out
639 void CSurfaceStream::SetReadBufferIndex(TInt aIndex)
641 __ASSERT_DEBUG(aIndex >= 0 && aIndex < iInfo.iBuffers,
642 (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferIndexOutOfBounds)));
643 iReadBuffer = aIndex;
646 TInt CSurfaceStream::GetReadBufferIndex()
650 TInt CSurfaceStream::GetWriteBufferIndex()
652 return (iReadBuffer+1)%iInfo.iBuffers;
655 /*! \brief Returns pointer to pixel buffer.
657 * \param buffer Handle of buffer
659 void* CSurfaceStream::GetBufferPtrL(SymbianStreamBuffer aBuffer)
661 TInt bufferIndex = BufferHandleToIndex(aBuffer);
662 Guard g1(iRefCountMutex);
663 __ASSERT_DEBUG(iBufferInfo[bufferIndex].iRefCount > 0,
664 (iRefCountMutex.Signal(),Panic(EOwfPanicSurfaceStreamBufferNotLocked)));
666 switch (SurfaceId().Type())
668 case TSurfaceTypes::ESurfaceManagerSurface:
670 if (iBufferChunk.Handle() == 0)
675 TInt err = sm.MapSurface(iSurfaceId, threadChunk);
677 CleanupClosePushL(threadChunk);
679 RChunk duplicateChunk;
680 duplicateChunk.SetHandle(threadChunk.Handle());
681 User::LeaveIfError(duplicateChunk.Duplicate(RThread(), EOwnerProcess));
683 iBufferChunk.SetHandle(duplicateChunk.Handle());
684 CleanupStack::PopAndDestroy(&threadChunk);
688 case TSurfaceId::EScreenSurface:
690 if (iBufferChunk.Handle() == 0)
693 TInt screenId = SurfaceId().iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField];
694 User::LeaveIfError(HAL::Get(screenId, HALData::EDisplayMemoryHandle, val));
697 CleanupClosePushL(threadChunk);
698 User::LeaveIfError(threadChunk.SetReturnedHandle(val));
700 RChunk duplicateChunk;
701 duplicateChunk.SetHandle(threadChunk.Handle());
702 User::LeaveIfError(duplicateChunk.Duplicate(RThread(), EOwnerProcess));
704 iBufferChunk.SetHandle(duplicateChunk.Handle());
705 CleanupStack::PopAndDestroy(&threadChunk);
710 User::Leave(KErrNotSupported);
713 TUint8 *pBufferStart = iBufferChunk.Base() + iBufferInfo[bufferIndex].iOffset;
714 return static_cast<void*>(pBufferStart);
717 void CSurfaceStream::SetProtectionFlag(TBool aFlag)
719 iRefCountMutex.Wait();
720 if (aFlag!=iProtected)
723 iRefCountMutex.Signal();
735 iRefCountMutex.Signal();
739 TInt CSurfaceStream::BytesPerPixel(TUidPixelFormat aPixelFormat)
741 switch (aPixelFormat)
743 case EUidPixelFormatXRGB_8888:
744 case EUidPixelFormatARGB_8888:
745 case EUidPixelFormatBGRX_8888:
746 case EUidPixelFormatXBGR_8888:
747 case EUidPixelFormatBGRA_8888:
748 case EUidPixelFormatABGR_8888:
749 case EUidPixelFormatABGR_8888_PRE:
750 case EUidPixelFormatARGB_8888_PRE:
751 case EUidPixelFormatBGRA_8888_PRE:
752 case EUidPixelFormatARGB_2101010:
753 case EUidPixelFormatABGR_2101010:
755 case EUidPixelFormatBGR_888:
756 case EUidPixelFormatRGB_888:
758 case EUidPixelFormatXRGB_4444:
759 case EUidPixelFormatARGB_4444:
760 case EUidPixelFormatXBGR_4444:
761 case EUidPixelFormatRGB_565:
762 case EUidPixelFormatBGR_565:
763 case EUidPixelFormatARGB_1555:
764 case EUidPixelFormatXRGB_1555:
765 case EUidPixelFormatARGB_8332:
766 case EUidPixelFormatBGRX_5551:
767 case EUidPixelFormatBGRA_5551:
768 case EUidPixelFormatBGRA_4444:
769 case EUidPixelFormatBGRX_4444:
770 case EUidPixelFormatAP_88:
772 case EUidPixelFormatRGB_332:
773 case EUidPixelFormatBGR_332:
774 case EUidPixelFormatA_8:
775 case EUidPixelFormatL_8:
777 case EUidPixelFormatP_8:
779 case EUidPixelFormatP_4:
780 case EUidPixelFormatL_4:
782 case EUidPixelFormatL_2:
783 case EUidPixelFormatP_2:
785 case EUidPixelFormatL_1 :
794 SymbianStreamBuffer CSurfaceStream::IndexToReadHandle(TInt aIndex)
796 return static_cast<SymbianStreamBuffer>(aIndex + BUFFER_READ_HANDLE_BASE);
799 SymbianStreamBuffer CSurfaceStream::IndexToWriteHandle(TInt aIndex)
801 return static_cast<SymbianStreamBuffer>(aIndex + BUFFER_WRITE_HANDLE_BASE);
804 TInt CSurfaceStream::BufferHandleToIndex(SymbianStreamBuffer aBuff)
806 TInt retVal= (aBuff > 0) ? (aBuff&0xFF) : (aBuff - BUFFER_READ_HANDLE_BASE);
807 __ASSERT_DEBUG(retVal>=0,User::Invariant());
808 __ASSERT_DEBUG(retVal<iInfo.iBuffers,User::Invariant());
815 void CSurfaceStream::RequestComplete(TThreadId& aThreadId, TRequestStatus*& aRequestStatus, TInt& aGlobalIndexArray, TInt aStatus)
819 if (aGlobalIndexArray != KInvalidIndex)
821 TGlobalNotification& globalNotification = iGlobalNotifications[aGlobalIndexArray];
822 --globalNotification.iPendingNotifications;
826 globalNotification.iCompletedOkNotifications++;
829 globalNotification.iOverflowedNotifications++;
832 globalNotification.iCanceledNotifications++;
835 globalNotification.iNotVisibleNotifications++;
838 globalNotification.iOtherNotifications++;
840 NFLOG(("### CSurfaceStream::RequestComplete globalRequestStatus[%d] iPendingNotifications(%d) "
841 "iCompletedOkNotifications(%d)"
842 "iOverflowedNotifications(%d)"
843 "iCanceledNotifications(%d)"
844 "iNotVisibleNotifications(%d)"
845 "iOtherNotifications(%d)"
848 globalNotification.iPendingNotifications,
849 globalNotification.iCompletedOkNotifications,
850 globalNotification.iOverflowedNotifications,
851 globalNotification.iCanceledNotifications,
852 globalNotification.iNotVisibleNotifications,
853 globalNotification.iOtherNotifications,
856 if (globalNotification.iStatus && globalNotification.iPendingNotifications == 0)
859 if (globalNotification.iCompletedOkNotifications > 0)
863 else if (globalNotification.iOverflowedNotifications > 0)
865 status = KErrOverflow;
867 else if (globalNotification.iNotVisibleNotifications > 0)
869 status = KErrNotVisible;
871 else if (globalNotification.iCanceledNotifications > 0)
877 status = KErrGeneral;
881 if (thread.Open(globalNotification.iThreadId) == KErrNone)
883 NFLOG(("### CSurfaceStream::RequestComplete globalIndex[%d] aRequestComplete(0x%x) status(%d)",
884 aGlobalIndexArray, iGlobalNotifications[aGlobalIndexArray].iStatus, status));
885 thread.RequestComplete(globalNotification.iStatus, status);
887 iGlobalNotifications[aGlobalIndexArray].Reset();
894 if (thread.Open(aThreadId) == KErrNone)
896 NFLOG(("### CSurfaceStream::RequestComplete aRequestStatus(0x%x) aThreadId(0x%x) aStatus(%d)",
897 aRequestStatus, aThreadId, aStatus));
898 thread.RequestComplete(aRequestStatus, aStatus);
902 aRequestStatus = NULL;
905 aGlobalIndexArray = KInvalidIndex;
908 int CSurfaceStream::AddObserver(SymbianStreamCallback aObserver,
910 TInt32 aScreenNumber,
913 if (!(aEvent & ESOWF_AllEventsMask) || !aData)
915 // early exit if the parameters are invalid
919 TInt errRet = KErrNone;
920 TCallBackEntry newEntry;
922 Guard g2(iCallBacksMutex);
923 Guard g1(iRefCountMutex);
925 // Let's do the check that we dont have an other similar observer already inserted
926 // traverse the whole aobservers list to see if there is already an observer in place
927 TInt idx = iCallBacks.Count();
930 if (iCallBacks[idx].iEventMask == aEvent)
934 case ESOWF_EventAvailable:
935 case ESOWF_EventDisplayed:
936 case ESOWF_EventDisplayedX:
937 // these are events related to a context and identified by a screen number
938 if (iCallBacks[idx].iScreenNumber == aScreenNumber)
940 // nothing else to do, the entry is already created
945 case ESOWF_EventComposed:
946 case ESOWF_EventUpdated:
947 if (iCallBacks[idx].iCallBackClientParam == aData)
949 // nothing else to do, the entry is already created
955 // something really unexpected, let's invalidate the entry
956 // possible memomry leaks but we are, still, alive and running.
957 iCallBacks[idx].Reset();
963 // we need to add a new observer to the list
964 newEntry.iCallBackFunction = aObserver;
965 newEntry.iEventMask = aEvent;
966 newEntry.iScreenNumber = aScreenNumber;
970 case ESOWF_EventUpdated:
971 case ESOWF_EventComposed:
972 newEntry.iCallBackClientParam = aData;
975 case ESOWF_EventAvailable:
977 TNotificationAvailable* available = NULL;
978 TRAP(trapErr,available = new(ELeave) TNotificationAvailable());
979 if (trapErr != KErrNone)
983 ResetCallBackData(available, aEvent);
984 available->iSerialNumber = KInitialContextSerialNumber;
985 newEntry.iCallBackClientParam = available;
989 case ESOWF_EventDisplayed:
991 TNotificationDisplayed* displayed = NULL;
992 TRAP(trapErr,displayed = new(ELeave) TNotificationDisplayed());
993 if (trapErr != KErrNone)
997 ResetCallBackData(displayed, aEvent);
998 displayed->iSerialNumber = KInitialContextSerialNumber;
999 newEntry.iCallBackClientParam = displayed;
1003 case ESOWF_EventDisplayedX:
1005 TNotificationDisplayedX* displayedX = NULL;
1006 TRAP(trapErr,displayedX = new(ELeave) TNotificationDisplayedX());
1007 if (trapErr != KErrNone)
1011 ResetCallBackData(displayedX, aEvent);
1012 displayedX->iSerialNumber = KInitialContextSerialNumber;
1013 newEntry.iCallBackClientParam = displayedX;
1018 return KErrArgument;
1021 // look for an entry that already exists
1022 idx = iCallBacks.Count();
1026 // the free entry positions are identified using event mask
1027 if (iCallBacks[idx].iEventMask == ESOWF_NoEvent) break;
1032 // ok, we got an existing, free entry
1033 iCallBacks[idx] = newEntry;
1037 errRet = iCallBacks.Append(newEntry);
1038 if (errRet != KErrNone)
1046 case ESOWF_EventAvailable:
1047 iNumberOfScreenAttachedAvailableNotif++;
1050 case ESOWF_EventDisplayed:
1051 iNumberOfScreenAttachedDisplayedNotif++;
1054 case ESOWF_EventDisplayedX:
1055 iNumberOfScreenAttachedDisplayedXNotif++;
1067 int CSurfaceStream::RemoveObserver(TInt32 aEvents, void* aData)
1069 NFLOG(("ENTER ###CSurfaceStream::RemoveObserver() events(%d) data(0x%x)", aEvents, aData));
1070 if (!(aEvents & ESOWF_AllEventsMask))
1072 NFLOG(("EXIT ###CSurfaceStream::RemoveObserver() ERROR: KErrArgument"));
1073 return KErrArgument;
1076 Guard g2(iCallBacksMutex);
1077 Guard g1(iRefCountMutex);
1079 TInt32 notFoundEvent = aEvents;
1080 TInt count = iCallBacks.Count();
1081 TInt32 susScreenNumber = KNoAssociatedScreenNumber;
1085 susScreenNumber = *(((TInt32*)aData));
1088 while (count-- && notFoundEvent)
1090 TInt32 currentEvent = iCallBacks[count].iEventMask;
1091 if (currentEvent & aEvents)
1093 void* callBackData = iCallBacks[count].iCallBackClientParam;
1094 switch (currentEvent)
1096 case ESOWF_EventDisplayed:
1097 if (callBackData && (!aData || (iCallBacks[count].iScreenNumber == susScreenNumber)))
1099 Displayed(ESOWF_ObserverCancel, iCallBacks[count].iScreenNumber, NULL, callBackData, NULL);
1100 delete (TNotificationDisplayed*) callBackData;
1101 iCallBacks[count].Reset();
1102 if (iNumberOfScreenAttachedDisplayedNotif > 0)
1104 iNumberOfScreenAttachedDisplayedNotif--;
1106 notFoundEvent &= ~currentEvent;
1110 case ESOWF_EventAvailable:
1111 if (callBackData && (!aData || (iCallBacks[count].iScreenNumber == susScreenNumber)))
1113 Available(ESOWF_ObserverCancel, iCallBacks[count].iScreenNumber, NULL, callBackData, NULL);
1114 delete (TNotificationAvailable*) callBackData;
1115 iCallBacks[count].Reset();
1116 if (iNumberOfScreenAttachedAvailableNotif > 0)
1118 iNumberOfScreenAttachedAvailableNotif--;
1120 notFoundEvent &= ~currentEvent;
1124 case ESOWF_EventDisplayedX:
1125 if (callBackData && (!aData || (iCallBacks[count].iScreenNumber == susScreenNumber)))
1127 DisplayedXTimes(ESOWF_ObserverCancel, iCallBacks[count].iScreenNumber, NULL, callBackData, NULL);
1128 delete (TNotificationDisplayedX*) callBackData;
1129 iCallBacks[count].Reset();
1130 if (iNumberOfScreenAttachedDisplayedXNotif)
1132 iNumberOfScreenAttachedDisplayedXNotif--;
1134 notFoundEvent &= ~currentEvent;
1138 case ESOWF_EventComposed:
1139 if (!aData || (aData == iCallBacks[count].iCallBackClientParam))
1141 // just in case that we have to delete the call back, we try, first to execute it
1142 // avoiding in this way some deadlocks in CT code
1143 if (iCallBacks[count].iCallBackFunction && iCallBacks[count].iCallBackClientParam)
1145 iCallBacks[count].iCallBackFunction(ToHandle(),
1146 ESOWF_EventComposed,
1147 iCallBacks[count].iCallBackClientParam,
1150 iCallBacks[count].Reset();
1151 notFoundEvent &= ~currentEvent;
1155 case ESOWF_EventUpdated:
1156 if (!aData || (aData == iCallBacks[count].iCallBackClientParam))
1158 if (iCallBacks[count].iScreenNumber != KNoAssociatedScreenNumber)
1160 susScreenNumber = iCallBacks[count].iScreenNumber;
1161 iCallBacks[count].Reset();
1162 notFoundEvent &= ~currentEvent;
1164 // Reseting variables to loop back and remove SUS events.
1165 notFoundEvent |= ESOWF_SUSEventsMask;
1166 aEvents = ESOWF_SUSEventsMask;
1167 count = iCallBacks.Count();
1171 iCallBacks[count].Reset();
1172 notFoundEvent &= ~currentEvent;
1183 NFLOG(("EXIT ###CSurfaceStream::CancelNotifications() err(%d)", notFoundEvent ? KErrNotFound : KErrNone));
1184 return (notFoundEvent ? KErrNotFound : KErrNone);
1187 TInt CSurfaceStream::NotifyObservers(TInt32 aEvent)
1189 NFLOG(("### ENTER CSurfaceStream::NotifyObservers()"));
1190 TInt err = KErrNotFound;
1192 Guard g2(iCallBacksMutex);
1193 TCallBackEntry localCallBackEntry;
1195 for (TInt i = 0; i < iCallBacks.Count(); ++i)
1197 localCallBackEntry = iCallBacks[i];
1198 if (iCallBacks[i].iEventMask & aEvent &&
1199 iCallBacks[i].iCallBackFunction)
1202 NFLOG(("### EXIT CSurfaceStream::NotifyObservers() callback(%d)", iCallBacks[i].iEventMask));
1203 localCallBackEntry.iCallBackFunction(ToHandle(),
1204 iCallBacks[i].iEventMask,
1205 localCallBackEntry.iCallBackClientParam,
1209 NFLOG(("### EXIT CSurfaceStream::NotifyObservers() err(%d)", err));
1213 TBool CSurfaceStream::NotifyComposerContext(TInt32 aScreenNumber, TInt aOp, SYMOWF_CONTENT_UPDATED_PARAM* aParam)
1215 NFLOG(("### ENTER CSurfaceStream::NotifyComposerContext()"));
1216 TCallBackEntry entry;
1218 for(TInt i = 0; i < iCallBacks.Count(); i++)
1220 if (iCallBacks[i].iEventMask == ESOWF_EventUpdated &&
1221 iCallBacks[i].iCallBackFunction &&
1222 (((iCallBacks[i].iScreenNumber == KNoAssociatedScreenNumber) && (aOp != SYM_CONTENT_UPDATE_BEGIN)) ||
1223 ((aScreenNumber == KNoAssociatedScreenNumber) && (aOp != SYM_CONTENT_UPDATE_BEGIN)) ||
1224 iCallBacks[i].iScreenNumber == aScreenNumber))
1226 entry = iCallBacks[i];
1227 iRefCountMutex.Signal();
1228 NFLOG(("###CSurfaceStream::NotifyComposerContext() ESOWF_EventUpdated aParam(%d)", aParam? aParam->id: -1));
1229 entry.iCallBackFunction(ToHandle(), ESOWF_EventUpdated, entry.iCallBackClientParam, aParam);
1231 // We are meant to hold this lock when we leave this function so coverity warning is false
1233 iRefCountMutex.Wait();
1236 NFLOG(("### EXIT CSurfaceStream::NotifyComposerContext() ret(%d)", ret));
1240 TBool CSurfaceStream::StartUpdateNotifications(TInt aScreenNumber, SYMOWF_CONTENT_UPDATED_PARAM& param)
1242 NFLOG(("### CSurfaceStream::StartUpdateNotifications()"));
1243 param.id = SYM_CONTENT_UPDATE_BEGIN;
1244 param.length = sizeof (param);
1246 param.serialNumber = KNoAssociatedScreenNumber;
1247 param.immediateAvailable = 0;
1248 return NotifyComposerContext(aScreenNumber, SYM_CONTENT_UPDATE_BEGIN, ¶m);
1251 TBool CSurfaceStream::EndUpdateNotifications(TInt aScreenNum, TInt aBufferNum, TInt32 aUpdatedFlags, const TRegion* aRegion)
1255 NFLOG(("### CSurfaceStream::EndUpdateNotifications()"));
1256 if (aBufferNum < 0 || aBufferNum >= iInfo.iBuffers)
1261 if (iAcquiredWriteBuffer != WFC_INVALID_HANDLE)
1263 iAcquiredWriteBuffer = BUFFER_WRITE_UPDATE_OVERWRITE;
1266 SetReadBufferIndex(aBufferNum);
1268 SYMOWF_CONTENT_UPDATED_PARAM param;
1269 param.length = sizeof (param);
1270 param.id = SYM_CONTENT_UPDATE_END;
1271 param.par = aUpdatedFlags;
1272 return NotifyComposerContext(aScreenNum, SYM_CONTENT_UPDATE_END, ¶m);
1275 TBool CSurfaceStream::UpdateNotifications(TInt aScreenNum,
1277 TInt32 aUpdatedFlags,
1278 const TRegion* aRegion)
1282 NFLOG(("### CSurfaceStream::UpdateNotifications()"));
1283 if (aBufferNum < 0 || aBufferNum >= iInfo.iBuffers)
1288 if (iAcquiredWriteBuffer != WFC_INVALID_HANDLE)
1290 iAcquiredWriteBuffer = BUFFER_WRITE_UPDATE_OVERWRITE;
1293 SetReadBufferIndex(aBufferNum);
1295 SYMOWF_CONTENT_UPDATED_PARAM param;
1296 param.length = sizeof (param);
1297 param.id = SYM_CONTENT_UPDATE;
1298 param.par = aUpdatedFlags;
1299 return NotifyComposerContext(aScreenNum, SYM_CONTENT_UPDATE, ¶m);
1302 void CSurfaceStream::SetNewNotifications(TInt aBuffer,
1303 TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
1304 TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
1305 TRequestStatus* aStatusConsumed, const TRegion* aRegion,
1306 TInt32 aScreenNumber)
1308 NFLOG(("### ENTER * CSurfaceStream::SetNewNotifications()"));
1309 Guard g2(iCallBacksMutex);
1310 Guard g1(iRefCountMutex);
1311 if (aScreenNumber == KAllScreens)
1313 SetAllNotifications(aBuffer,
1314 aStatusDisplayed, aTimeStamp,
1315 aStatusDispXTimes, aDisplayedXTimes,
1316 aStatusConsumed, aRegion);
1320 TNewGlobalNotifications noGlobalNotifications;
1321 SetNotifications(aBuffer,
1322 aStatusDisplayed, aTimeStamp,
1323 aStatusDispXTimes, aDisplayedXTimes,
1324 aStatusConsumed, aRegion,
1325 aScreenNumber, noGlobalNotifications);
1327 NFLOG(("### EXIT * CSurfaceStream::SetNewNotifications()"));
1331 void CSurfaceStream::SetNotifications(TInt aBuffer,
1332 TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
1333 TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
1334 TRequestStatus* aStatusConsumed, const TRegion* aRegion,
1335 TInt32 aScreenNumber, const TNewGlobalNotifications& aGlobalNotifications)
1337 NFLOG(("### ENTER * CSurfaceStream::SetNotifications()"));
1338 TInt32 eventsFound = 0;
1339 TInt32 eventsReceived = 0;
1340 TInt32 eventsToProcess = 0;
1341 TInt32 contextUpdate = 0;
1342 // let's take in evidence the events we have to process
1343 if (aStatusConsumed)
1345 eventsReceived |= ESOWF_EventAvailable;
1347 if (aStatusDisplayed)
1349 eventsReceived |= ESOWF_EventDisplayed;
1351 if (aStatusDispXTimes)
1353 eventsReceived |= ESOWF_EventDisplayedX;
1356 TInt availableIndex = -1;
1357 TInt displayedIndex = -1;
1358 TInt displayedXIndex = -1;
1360 TInt32 serialNumber = KNoAssociatedScreenNumber;
1361 TBool immediateAvailable = EFalse;
1362 TInt32 immediateVisibility = SYM_CONTENT_VISIBLE_NOT_SET;
1364 // guard acquiring/release of the update lock of the composer
1365 // acquire the update lock of the composer and retrive the composer state info
1366 SYMOWF_CONTENT_UPDATED_PARAM param;
1367 TBool startUpdateNotification = StartUpdateNotifications(aScreenNumber, param);
1368 immediateAvailable = param.immediateAvailable && ETrue;
1369 immediateVisibility = param.immediateVisibility;
1370 serialNumber = param.serialNumber;
1373 // we take, initially in consideration "available" even if we might not have received a consumed request status
1374 eventsToProcess = 0;
1376 // we try to figure out which are the events we have to process and to get hold of their position
1377 // in the observers array, in order to avoid traversing it again
1378 TInt idx = iCallBacks.Count();
1379 //we will intend to mark the visited events, as an optimisation
1380 TInt32 eventsToCheck = eventsReceived | ESOWF_EventAvailable;
1381 TInt32 currentEvent = 0;
1382 while(--idx > -1 && eventsToCheck)
1384 currentEvent = iCallBacks[idx].iEventMask;
1385 if ((currentEvent & eventsToCheck) && (iCallBacks[idx].iScreenNumber == aScreenNumber))
1387 switch (currentEvent)
1389 case ESOWF_EventAvailable:
1390 // mark observer visited
1391 eventsToCheck &= ~currentEvent;
1392 // mark the events found only if the corresponding status request has been recived
1393 eventsFound |= (currentEvent & eventsReceived);
1394 // reset the events to process mask
1395 eventsToProcess &= ~currentEvent;
1397 TNotificationAvailable* available = (TNotificationAvailable*) iCallBacks[idx].iCallBackClientParam;
1398 if (available && (aStatusConsumed || available->iStatus || available->iNewStatus))
1400 // set the mask of the events to be processed because we have either to overflow some available request
1401 // statuses, or to process them further
1402 eventsToProcess |= ESOWF_EventAvailable;
1403 availableIndex = idx;
1408 case ESOWF_EventDisplayed:
1409 // mark observer visited
1410 eventsFound |= currentEvent;
1411 eventsToProcess |= currentEvent;
1412 eventsToCheck &= ~currentEvent;
1413 displayedIndex = idx;
1416 case ESOWF_EventDisplayedX:
1417 // mark observer visited
1418 eventsFound |= currentEvent;
1419 eventsToProcess |= currentEvent;
1420 eventsToCheck &= ~currentEvent;
1421 displayedXIndex = idx;
1425 Panic(EOwfSymbianUnexpectedObserverId);
1431 NFLOG(("### CSurfaceStream::SetNotifications eventsToProcess(0x%x)", eventsToProcess));
1432 if (eventsToProcess)
1435 // from this momment on, the composer cannot process any notifications related to this stream
1437 ContentUpdatedParams updateParameters(aBuffer, aStatusDisplayed, aTimeStamp,
1438 aStatusDispXTimes, aDisplayedXTimes,
1439 aStatusConsumed, aRegion,
1440 immediateAvailable, immediateVisibility,
1441 aGlobalNotifications);
1443 // process the observer corresponding to aStatusConsumed request status
1444 if ((ESOWF_EventAvailable & eventsToProcess) && (availableIndex > -1))
1446 Available(ESOWF_ObserverProcessing,
1449 iCallBacks[availableIndex].iCallBackClientParam,
1453 // process the observer corresponding to aStatusDisplayed request status
1454 if ((ESOWF_EventDisplayed & eventsToProcess) && (displayedIndex > -1))
1456 Displayed(ESOWF_ObserverProcessing,
1459 iCallBacks[displayedIndex].iCallBackClientParam,
1463 // process the observer corresponding to aStatusDispXTimes request status
1464 if ((ESOWF_EventDisplayedX & eventsToProcess) && (displayedXIndex > -1))
1466 DisplayedXTimes(ESOWF_ObserverProcessing,
1469 iCallBacks[displayedXIndex].iCallBackClientParam,
1475 if (startUpdateNotification)
1477 EndUpdateNotifications(aScreenNumber, aBuffer, contextUpdate, aRegion);
1481 UpdateNotifications(aScreenNumber, aBuffer, contextUpdate, aRegion);
1484 if (eventsReceived != eventsFound)
1486 if (aStatusConsumed && !(eventsFound & ESOWF_EventAvailable))
1488 User::RequestComplete(aStatusConsumed, KErrCancel);
1491 if (aStatusDisplayed && !(eventsFound & ESOWF_EventDisplayed))
1494 User::RequestComplete(aStatusDisplayed, KErrCancel);
1497 if (aStatusDispXTimes && !(eventsFound & ESOWF_EventDisplayedX))
1499 User::RequestComplete(aStatusDispXTimes, KErrCancel);
1502 NFLOG(("### EXIT * CSurfaceStream::SetNotifications()"));
1505 TInt CSurfaceStream::AddNewGlobalNotification(TRequestStatus* aStatusDisplayed, TInt aAssociatedScreens)
1507 TInt maxIdx = iGlobalNotifications.Count();
1508 TInt retIdx = KInvalidIndex;
1509 for (TInt i = 0; i < maxIdx; i++)
1511 if (iGlobalNotifications[i].iStatus == NULL)
1513 NFLOG(("### ENTER * CSurfaceStream::AddNewGlobalNotification found free idx(%d)", i));
1519 if (retIdx == KInvalidIndex)
1521 TGlobalNotification newNotification;
1522 if (iGlobalNotifications.Append(newNotification) == KErrNone)
1524 retIdx = iGlobalNotifications.Count() - 1;
1528 if (retIdx != KInvalidIndex)
1530 NFLOG(("### ENTER * CSurfaceStream::AddNewGlobalNotification populating idx(%d, status(%p) associated screens=0x%x)", retIdx, aStatusDisplayed, aAssociatedScreens));
1531 iGlobalNotifications[retIdx].Reset();
1532 iGlobalNotifications[retIdx].iStatus = aStatusDisplayed;
1533 iGlobalNotifications[retIdx].iThreadId = RThread().Id();
1534 iGlobalNotifications[retIdx].iPendingNotifications = aAssociatedScreens;
1540 void CSurfaceStream::SetAllNotifications(TInt aBuffer,
1541 TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
1542 TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
1543 TRequestStatus* aStatusConsumed, const TRegion* aRegion)
1545 NFLOG(("### ENTER * CSurfaceStream::SetAllNotifications()"));
1546 TInt32 eventsToProcess = 0;
1547 // let's take in evidence the events we have to process
1549 TNewGlobalNotifications newGlobalNotifications;
1552 if (aStatusConsumed && iNumberOfScreenAttachedAvailableNotif > 0)
1554 if ((idx = AddNewGlobalNotification(aStatusConsumed, iNumberOfScreenAttachedAvailableNotif)) != KInvalidIndex)
1556 newGlobalNotifications.iNewAvailableIdx = idx;
1557 eventsToProcess |= ESOWF_EventAvailable;
1561 if (aStatusDisplayed && iNumberOfScreenAttachedDisplayedNotif > 0)
1563 if ((idx = AddNewGlobalNotification(aStatusDisplayed, iNumberOfScreenAttachedDisplayedNotif)) != KInvalidIndex)
1565 newGlobalNotifications.iNewDisplayedIdx = idx;
1566 eventsToProcess |= ESOWF_EventDisplayed;
1570 if (aStatusDispXTimes && iNumberOfScreenAttachedDisplayedXNotif > 0)
1572 if ((idx = AddNewGlobalNotification(aStatusDispXTimes, iNumberOfScreenAttachedDisplayedXNotif)) != KInvalidIndex)
1574 newGlobalNotifications.iNewDisplayedXIdx = idx;
1575 eventsToProcess |= ESOWF_EventDisplayedX;
1579 NFLOG(("### CSurfaceStream::SetAllNotifications eventsToProcess(0x%x)", eventsToProcess));
1581 idx = iCallBacks.Count();
1582 TInt prevScreenNumber = KNoAssociatedScreenNumber;
1583 TInt screenNumber = KNoAssociatedScreenNumber;
1584 idx = iCallBacks.Count();
1587 if (iCallBacks[idx].iCallBackClientParam &&
1588 (iCallBacks[idx].iEventMask == ESOWF_EventUpdated) &&
1589 ((screenNumber = iCallBacks[idx].iScreenNumber) != KNoAssociatedScreenNumber)
1590 && prevScreenNumber != screenNumber)
1592 NFLOG(("### CSurfaceStream::SetAllNotifications update composer %d", screenNumber));
1593 SetNotifications(aBuffer,
1594 aStatusDisplayed, aTimeStamp,
1595 aStatusDispXTimes, aDisplayedXTimes,
1596 aStatusConsumed, aRegion, screenNumber, newGlobalNotifications);
1598 prevScreenNumber = screenNumber;
1603 if (aStatusConsumed && !(eventsToProcess & ESOWF_EventAvailable))
1605 User::RequestComplete(aStatusConsumed, KErrCancel);
1608 if (aStatusDisplayed && !(eventsToProcess & ESOWF_EventDisplayed))
1611 User::RequestComplete(aStatusDisplayed, KErrCancel);
1614 if (aStatusDispXTimes && !(eventsToProcess & ESOWF_EventDisplayedX))
1616 User::RequestComplete(aStatusDispXTimes, KErrCancel);
1618 NFLOG(("### EXIT * CSurfaceStream::SetAllNotifications()"));
1622 void CSurfaceStream::ProcessNotifications(TInt32 aEvent,
1623 TInt32 aScreenNumber,
1625 TInt32 aSerialNumber,
1626 TInt32* aReturnMask)
1628 Guard g(iRefCountMutex);
1629 NFLOG(("### ENTER CSurfaceStream::ProcessNotifications()"));
1631 TInt32 eventsToFind = aEvent & ESOWF_SUSEventsMask;
1632 TInt idx = iCallBacks.Count();
1633 while(idx-- && eventsToFind)
1635 TInt32 currentEvent = iCallBacks[idx].iEventMask;
1636 if (currentEvent & aEvent)
1638 TNotificationBase* notifBase = (TNotificationBase*) iCallBacks[idx].iCallBackClientParam;
1639 if (notifBase && notifBase->iStatus && iCallBacks[idx].iScreenNumber == aScreenNumber)
1641 TInt callBackOperation = (aOperation == EDefaultOperation) ? currentEvent : ESOWF_ObserverCheckVisible;
1642 eventsToFind &= ~currentEvent;
1643 switch (currentEvent)
1645 case ESOWF_EventAvailable:
1646 Available(callBackOperation, aSerialNumber, NULL, iCallBacks[idx].iCallBackClientParam, aReturnMask);
1649 case ESOWF_EventDisplayed:
1650 Displayed(callBackOperation, aSerialNumber, NULL, iCallBacks[idx].iCallBackClientParam, aReturnMask);
1653 case ESOWF_EventDisplayedX:
1654 DisplayedXTimes(callBackOperation, aSerialNumber, NULL, iCallBacks[idx].iCallBackClientParam, aReturnMask);
1663 NFLOG(("### EXIT CSurfaceStream::ProcessNotifications()"));
1666 TInt CSurfaceStream::CheckBufferNumber(TInt aBuffer,
1667 TRequestStatus* aStatusDisplayed,
1668 TRequestStatus* aStatusDispXTimes,
1669 TRequestStatus* aStatusConsumed)
1671 if (aBuffer < 0 || aBuffer >= iInfo.iBuffers)
1673 if (aStatusConsumed)
1675 User::RequestComplete(aStatusConsumed, KErrArgument);
1677 if (aStatusDisplayed)
1679 User::RequestComplete(aStatusDisplayed, KErrArgument);
1681 if (aStatusDispXTimes)
1683 User::RequestComplete(aStatusDispXTimes, KErrArgument);
1685 return KErrArgument;
1693 void CSurfaceStream::Available(TInt32 aEvent,
1694 TInt32 aSerialNumber,
1695 ContentUpdatedParams* aParams,
1696 void* aCallBackData,
1697 TInt32* aReturnMask)
1700 NFLOG(("### ENTER CSurfaceStream::Available aEvent(0x%x) aSerialNumber(0x%x) "
1701 "aParams(0x%x) aCallBackData(0x%x) aReturnMask(0x%x)",
1702 aEvent, aSerialNumber, aParams, aCallBackData, aReturnMask));
1704 TNotificationAvailable* callBackData = (TNotificationAvailable*) aCallBackData;
1712 case ESOWF_ObserverProcessing:
1713 NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing"));
1714 // when a new available notification request is issued by SUS, we have to:
1715 // 1. Overflow the old request status (GCE behaviour)
1716 // 2. Update the observer
1717 // 3. If immediate availabilty chec if the old request status can be completed
1718 // 4. Inform the composer about any active available notifications requests
1722 // let's check first for overflow conditions
1723 // and overflow the oldest if exists (GCE behaviour)
1724 if (callBackData->iStatus)
1726 NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing Overflow"));
1727 // oldest notifications is overflowed (like GCE behaviour)
1728 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrOverflow);
1729 callBackData->iStatus = NULL;
1730 callBackData->iThreadId = 0;
1731 callBackData->iBufferNumber = -1;
1734 // propagate the new data
1735 callBackData->iSerialNumber = aSerialNumber;
1736 TBool multibuffered = iInfo.iBuffers > 1;
1739 callBackData->iStatus = callBackData->iNewStatus;
1740 callBackData->iThreadId = callBackData->iNewThreadId;
1741 callBackData->iBufferNumber = callBackData->iNewBufferNumber;
1742 callBackData->iGlobalIndex = callBackData->iNewGlobalIndex;
1746 callBackData->iStatus = aParams->iStatusConsumed;
1747 callBackData->iThreadId = RThread().Id();
1748 callBackData->iBufferNumber = aParams->iBuffer;
1749 callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewAvailableIdx;
1752 // the availability can be immediately completed if the
1753 // visibility status is known and the composer is not composing at that momment
1754 if (callBackData->iStatus && aParams->iImmediateAvailable)
1756 NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing Immediate Available"));
1757 if (iAcquiredWriteBuffer != WFC_INVALID_HANDLE)
1759 iAcquiredWriteBuffer = BUFFER_WRITE_UPDATE_OVERWRITE;
1762 SetReadBufferIndex(aParams->iBuffer);
1763 // immediate notification is possible because the context
1764 // is not composing at this momment
1765 if (aParams->iImmediateVisibility == SYM_CONTENT_NOT_VISIBLE)
1767 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNotVisible);
1771 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNone);
1773 ResetCallBackData(callBackData, aEvent);
1778 callBackData->iNewStatus = aParams->iStatusConsumed;
1779 callBackData->iNewThreadId = RThread().Id();
1780 callBackData->iNewBufferNumber = aParams->iBuffer;
1781 callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewAvailableIdx;
1784 // let the composer know that the Availability has to be analysed further
1785 if (aReturnMask && callBackData->iStatus)
1787 NFLOG(("###CSurfaceStream::Available ESOWF_ObserverProcessing *aReturnMask |= ESOWF_EventAvailable"));
1788 *aReturnMask |= ESOWF_EventAvailable;
1794 case ESOWF_EventAvailable:
1795 NFLOG(("###CSurfaceStream::Available ESOWF_EventAvailable"));
1796 if (callBackData->iStatus)
1798 // if it is an event just added during composition, we wxpect the same serial number
1799 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNone);
1800 // clean the old reques notification related info
1801 callBackData->iSerialNumber = aSerialNumber;
1802 callBackData->iStatus = NULL;
1803 callBackData->iThreadId = 0;
1804 callBackData->iBufferNumber = -1;
1808 case ESOWF_ObserverCheckVisible:
1809 NFLOG(("###CSurfaceStream::Available ESOWF_ObserverCheckVisible"));
1810 if (callBackData->iStatus)
1812 // complete the old request status (standard GCE behaviour)
1813 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrNotVisible);
1814 // clean the old reques notification related info
1815 callBackData->iSerialNumber = aSerialNumber;
1816 callBackData->iStatus = NULL;
1817 callBackData->iThreadId = 0;
1818 callBackData->iBufferNumber = -1;
1822 case ESOWF_ObserverCancel:
1824 NFLOG(("###CSurfaceStream::Available ESOWF_ObserverCancel"));
1825 // cancel both requests if they are valid
1826 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrCancel);
1827 RequestComplete(callBackData->iNewThreadId, callBackData->iNewStatus, callBackData->iGlobalIndex, KErrCancel);
1828 ResetCallBackData(callBackData, aEvent);
1835 NFLOG(("EXIT ###CSurfaceStream::Available()"));
1839 void CSurfaceStream::Displayed(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask)
1841 TInt notification = KErrNone;
1843 NFLOG(("### ENTER CSurfaceStream::Displayed aEvent(0x%x) aSerialNumber(0x%x) "
1844 "aParams(0x%x) aCallBackData(0x%x) aReturnMask(0x%x)",
1845 aEvent, aSerialNumber, aParams, aCallBackData, aReturnMask));
1846 TNotificationDisplayed* callBackData = (TNotificationDisplayed*) aCallBackData;
1854 case ESOWF_ObserverProcessing:
1855 NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverProcessing"));
1856 // When a new available notification request is issued by SUS, we have to:
1857 // 1. Overflow the previous request status
1858 // 2. Update the observer
1859 // 3. Inform the composer about any active available notifications requests
1861 if (callBackData->iStatus)
1863 NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverProcessing Overflowing"));
1864 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrOverflow);
1865 ResetCallBackData(callBackData, aEvent);
1867 if (aParams && aParams->iStatusDisplayed)
1869 __ASSERT_DEBUG(aParams->iTimeStamp,
1870 (iRefCountMutex.Signal(),Panic(EOwfInvalidSUSDisplayedParameter)));
1871 callBackData->iStatus = aParams->iStatusDisplayed;
1872 callBackData->iThreadId = RThread().Id();
1873 callBackData->iBufferNumber = aParams->iBuffer;
1874 callBackData->iSerialNumber = aSerialNumber;
1875 callBackData->iTimeStamp = aParams->iTimeStamp;
1876 callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewDisplayedIdx;
1877 NFLOG(("###CSurfaceStream::Displayed iGlobalIndex(%d)", callBackData->iGlobalIndex));
1879 if (aReturnMask && callBackData->iStatus)
1881 NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverProcessing *aReturnMask |= ESOWF_EventDisplayed"));
1882 *aReturnMask |= ESOWF_EventDisplayed;
1886 case ESOWF_EventDisplayed:
1887 // this invoked by composer
1888 NFLOG(("###CSurfaceStream::Displayed ESOWF_EventDisplayed"));
1889 if (!callBackData->iStatus)
1891 // no active notification, nothing to do
1892 NFLOG(("###CSurfaceStream::Displayed ESOWF_EventDisplayed no active notifications"));
1895 // deffer for next composition the processing if the updated happended during a composition
1896 if (callBackData->iSerialNumber == aSerialNumber && aReturnMask)
1898 NFLOG(("###CSurfaceStream::Displayed ESOWF_EventDisplayed *aReturnMask |= ESOWF_EventDisplayed"));
1899 *aReturnMask |= ESOWF_EventDisplayed;
1902 // complete the active request status
1903 callBackData->iSerialNumber = aSerialNumber;
1904 *callBackData->iTimeStamp = User::FastCounter();
1905 notification = KErrNone;
1908 case ESOWF_ObserverCheckVisible:
1909 // visibility check comming from composer
1910 NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverCheckVisible"));
1911 if (!callBackData->iStatus)
1913 // deffer for next composition the processing if the updated happended during a composition
1914 // or if no active notification, nothing to do
1915 NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverCheckVisible = Not Visible"));
1918 notification = KErrNotVisible;
1919 callBackData->iSerialNumber = aSerialNumber;
1922 case ESOWF_ObserverCancel:
1923 // cancel the active notification
1924 NFLOG(("###CSurfaceStream::Displayed ESOWF_ObserverCancel"));
1925 if (!callBackData->iStatus)
1929 notification = KErrCancel;
1936 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, notification);
1937 ResetCallBackData(callBackData, aEvent);
1938 NFLOG(("EXIT ###CSurfaceStream::Displayed()"));
1941 void CSurfaceStream::DisplayedXTimes(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask)
1943 TInt notification = KErrNone;
1945 NFLOG(("### ENTER CSurfaceStream::DisplayedXTimes aEvent(0x%x) aSerialNumber(0x%x) "
1946 "aParams(0x%x) aCallBackData(0x%x) aReturnMask(0x%x)",
1947 aEvent, aSerialNumber, aParams, aCallBackData, aReturnMask));
1949 TNotificationDisplayedX* callBackData = (TNotificationDisplayedX*) aCallBackData;
1957 case ESOWF_ObserverProcessing:
1958 // When a new available notification request is issued by SUS, we have to:
1959 // 1. Overflow the previous request status
1960 // 2. Update the observer
1961 // 3. Inform the composer about any active available notifications requests
1962 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverProcessing"));
1963 if (callBackData->iStatus)
1965 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverProcessing Overflowing"));
1966 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, KErrOverflow);
1967 ResetCallBackData(callBackData, aEvent);
1969 if (aParams && aParams->iStatusDispXTimes)
1971 __ASSERT_DEBUG(aParams->iDisplayedXTimes && *aParams->iDisplayedXTimes >= 1,
1972 (iRefCountMutex.Signal(),Panic(EOwfInvalidSUSDisplayedXTimesParameter)));
1973 callBackData->iStatus = aParams->iStatusDispXTimes;
1974 callBackData->iThreadId = RThread().Id();
1975 callBackData->iBufferNumber = aParams->iBuffer;
1976 callBackData->iSerialNumber = aSerialNumber;
1977 callBackData->iCount = *aParams->iDisplayedXTimes;
1978 callBackData->iGlobalIndex = aParams->iGlobalNotifications.iNewDisplayedXIdx;
1981 if (aReturnMask && callBackData->iStatus)
1983 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverProcessing *aReturnMask |= ESOWF_EventDisplayedX"));
1984 *aReturnMask |= ESOWF_EventDisplayedX;
1988 case ESOWF_EventDisplayedX:
1989 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX"));
1990 if (!callBackData->iStatus)
1992 // no active notification, nothing to do
1996 // deffer for next composition the processing if the updated happended during a composition
1997 if (callBackData->iSerialNumber == aSerialNumber)
2001 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX *aReturnMask |= ESOWF_EventDisplayedX"));
2002 *aReturnMask |= ESOWF_EventDisplayedX;
2007 callBackData->iSerialNumber = aSerialNumber;
2009 // complete the active request status
2010 if (callBackData->iCount > 1)
2012 // inform the composer a new notification is needed
2013 callBackData->iCount--;
2016 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX *aReturnMask |= ESOWF_EventDisplayedX iCount(%d)", callBackData->iCount));
2017 *aReturnMask |= ESOWF_EventDisplayedX;
2022 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_EventDisplayedX iCount(%d)", callBackData->iCount));
2023 notification = KErrNone;
2026 case ESOWF_ObserverCheckVisible:
2027 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverCheckVisible"));
2028 // visibility check comming from composer
2029 if (!callBackData->iStatus ||
2030 callBackData->iSerialNumber == aSerialNumber)
2032 // deffer for next composition the processing if the updated happended during a composition
2033 // or if no active notification, nothing to do
2036 callBackData->iSerialNumber = aSerialNumber;
2037 notification = KErrNotVisible;
2040 case ESOWF_ObserverCancel:
2041 // cancel the active notification
2042 NFLOG(("###CSurfaceStream::DisplayedXTimes ESOWF_ObserverCancel"));
2043 if (!callBackData->iStatus)
2047 notification = KErrCancel;
2054 RequestComplete(callBackData->iThreadId, callBackData->iStatus, callBackData->iGlobalIndex, notification);
2055 ResetCallBackData(callBackData, aEvent);
2056 NFLOG(("EXIT ###CSurfaceStream::DisplayedXTimes()"));
2059 void CSurfaceStream::ResetCallBackData(void* aCallBackData,
2064 case ESOWF_EventAvailable:
2066 TNotificationAvailable* available = (TNotificationAvailable*) aCallBackData;
2067 available->iStatus = NULL;
2068 available->iThreadId = 0;
2069 available->iBufferNumber = -1;
2070 available->iGlobalIndex = KInvalidIndex;
2071 available->iNewBufferNumber = -1;
2072 available->iNewStatus = NULL;
2073 available->iNewThreadId = 0;
2074 available->iNewGlobalIndex = KInvalidIndex;
2078 case ESOWF_EventDisplayed:
2080 TNotificationDisplayed* displayed = (TNotificationDisplayed*) aCallBackData;
2081 displayed->iStatus = NULL;
2082 displayed->iThreadId = 0;
2083 displayed->iBufferNumber = -1;
2084 displayed->iTimeStamp = NULL;
2085 displayed->iGlobalIndex = KInvalidIndex;
2089 case ESOWF_EventDisplayedX:
2091 TNotificationDisplayedX* displayed = (TNotificationDisplayedX*) aCallBackData;
2092 displayed->iStatus = NULL;
2093 displayed->iThreadId = 0;
2094 displayed->iBufferNumber = -1;
2095 displayed->iCount = 0;
2096 displayed->iGlobalIndex = KInvalidIndex;
2105 void CSurfaceStream::CancelNotifications()
2107 NFLOG(("ENTER ###CSurfaceStream::CancelNotifications()"));
2108 TInt cancelEvents = ESOWF_AllEventsMask;
2109 RemoveObserver(cancelEvents, NULL);
2110 NFLOG(("EXIT ###CSurfaceStream::CancelNotifications()"));
2113 TInt CSurfaceStream::Stride(TInt aWidth, TUidPixelFormat aPixelFormat)
2116 TInt bytesPerPixel = BytesPerPixel(aPixelFormat);
2118 if (bytesPerPixel >= 0)
2120 return bytesPerPixel * aWidth; // number of bytes between start of one line and start of next
2124 return (aWidth-(bytesPerPixel+1)) / (-bytesPerPixel);
2128 void CSurfaceStream::SetFlipState(TBool aFlip)
2130 Guard g1(iRefCountMutex);
2133 iNewFlip = EFlippedTargetFlipped;
2137 iNewFlip = EFlippedTargetNormal;
2141 TInt CSurfaceStream::GetChunkHandle()
2143 return iBufferChunk.Handle();