// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// SurfaceStream.h
// CSurfaceStream declaration
#ifndef SURFACESTREAM_H
#define SURFACESTREAM_H
// INCLUDES
#include <e32base.h>
#include <e32def.h>
#include <e32debug.h>
#include <graphics/surface.h>
#include <pixelformats.h>
#include <graphics/surfacemanager.h>
#include "symbianstream.h"
#if defined(ENABLE_NF_LOGGING)
#define NFLOG(X) RDebug::Printf X
#else
#define NFLOG(X)
#endif
// CLASS DECLARATION
// Each surface buffer has its corresponding TBufferInfo to hold reference count and memory offset
struct TBufferInfo
{
TInt iRefCount;
TInt iOffset;
};
// Notification data
struct TNotificationBase
{
TRequestStatus* iStatus;
TThreadId iThreadId;
TInt iBufferNumber;
TInt iSerialNumber;
TInt iGlobalIndex;
};
struct TNotificationDisplayed: public TNotificationBase
{
TUint32* iTimeStamp;
};
struct TNotificationDisplayedX: public TNotificationBase
{
TInt iCount;
};
struct TNotificationAvailable: public TNotificationBase
{
TRequestStatus* iNewStatus;
TThreadId iNewThreadId;
TInt iNewBufferNumber;
TInt iNewGlobalIndex;
};
class COpenWfcStreamMap;
/**
* CSurfaceStream
* internal
*/
NONSHARABLE_CLASS( CSurfaceStream ) : public CBase
{
struct TNewGlobalNotifications;
private:
class Guard
{
public:
Guard(RFastLock& aLock);
~Guard();
private:
RFastLock& iLock;
RHeap* iHeap;
};
struct ContentUpdatedParams
{
ContentUpdatedParams(TInt aBuffer,
TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
TRequestStatus* aStatusConsumed, const TRegion* aRegion,
TBool aImmediateAvailable,
TInt32 aImmediateVisibility, const TNewGlobalNotifications& aGlobalNotifications);
TInt iBuffer;
TRequestStatus* iStatusDisplayed;
TUint32* iTimeStamp;
TRequestStatus* iStatusDispXTimes;
TInt* iDisplayedXTimes;
TRequestStatus* iStatusConsumed;
const TRegion* iRegion;
TBool iImmediateAvailable;
TInt32 iImmediateVisibility;
const TNewGlobalNotifications& iGlobalNotifications;
};
public:
enum CallBackOperations
{
EDefaultOperation,
ECheckVisibleOperation
};
public:
// Constructors and destructor
/**
* Destructor.
*/
~CSurfaceStream();
/**
* Two-phased constructor.
*/
static CSurfaceStream* NewL(const TSurfaceId& aId);
/**
* Two-phased constructor.
*/
static CSurfaceStream* NewLC(const TSurfaceId& aId);
/**
Helper to resolve handle to stream object
**/
static CSurfaceStream* FromHandle(SymbianStreamType aNativeStreamHandle);
/**
* A helper function that returns the bytes per pixel for a given pixel format UID
* @param aPixelFormat Pixel format UID to convert
* @return Positive: bytes per pixel; negative is pixels per byte; 0 is error
*/
static TInt BytesPerPixel(TUidPixelFormat aPixelFormat);
/**
Helper to resolve handle to stream object
**/
SymbianStreamType ToHandle();
public:
//Internal helpers
/** Returns internal surface ID.
*
* @return surface id asociated with this stream
**/
const TSurfaceId& SurfaceId()const;
public:
//OpenWF-C SI/CT/MIG API implementation
/**
* Increase stream's reference count by one.
*
*/
void
AddReference();
/**
* Decrease stream's reference count by one and destroy
* the stream, if the reference count goes to zero.
*
* All acquired read & write buffers must be released
* before calling WFC_Native_Destroy.
*
*/
void
ReleaseReference();
/**
* internal
*
* @return flag if reference count is now zero.
*
*/
TBool
RemainingReference();
/**
* internal
*
* Sets flipped state.
*
*/
void
SetFlipState(TBool aFlip);
/**
* Get stream "frame header". Can be used to query
* all or some of the frame properties.
*
* @param width Pointer to location where width parameter should be saved
* @param height Pointer to location where height parameter should be saved
* @param stride Pointer to location where stride (row size in bytes)
* parameter should be saved
* @param pixelSize Pointer to location where pizelSize (pixel size in bytes)
* parameter should be saved
* Passing a NULL pointer implies that particular
* value is of no interest to caller. E.g.
* GetHeader(stream, &w, &h, NULL, NULL, NULL);
* would only fetch width & height parameters.
*/
void
GetHeader(khronos_int32_t* width,
khronos_int32_t* height,
khronos_int32_t* stride,
SymOwfPixelFormat* format,
khronos_int32_t* pixelSize);
/**
* Acquires read buffer for stream. For > 1 buffer
* streams this function doesn't block, but simply returns
* WFC_INVALID_HANDLE if no buffer is available for reading.
* For 1 buffer stream the caller is blocked until the buffer
* is ready for reading (the reader has committed the buffer,
* that is.)
*
*
* @return WFC_INVALID_HANDLE if no buffer is available or
* handle to last committed buffer.
*
* An example sequence for 3 buffer stream where
* producer produces frames approx. after every ~5th time unit.
* Consumer consumes buffers at constant rate of 1buf/time unit.
* Pframe is the number/handle of buffer that is being written by
* the producer (let's assume that it takes 2 time units
* for producer to produce a frame/buffer.) Cframe is the number/
* handle of the buffer the consumer receives from AcquireReadBuffer().
* "i" stands for WFC_INVALID_HANDLE:
*
* Time: 0 5 10 15 20 25
* Pframe: 0 1 2 0 1 ...
* Cframe: ii00000111112222200000111...
*/
SymbianStreamBuffer
AcquireReadBuffer();
/**
* Releases read buffer.
*
* When read buffer is released, it is marked as clean to
* be written again, unless it is the only committed buffer
* in which case it is recycled so that the same buffer
* can be read again (as long as no new buffers are committed
* by the producer)
*
* @param buf Buffer handle. Must be valid read buffer handle for
* given stream.
* @return KErrNone if succeessful or KErrBadHandle if buf is not a currently
* open write buffer on this stream;
*/
TInt
ReleaseReadBuffer(SymbianStreamBuffer buf);
/**
* Acquires write buffer for stream.
*
* Returns handle to a buffer that can be used to write
* data into stream. If no clean buffer is available,
* invalid handle is returned.
*
*
* @return Handle to a writable buffer
*/
SymbianStreamBuffer
AcquireWriteBuffer();
/**
* Releases write buffer to stream.
* Released buffer is made new front buffer, i.e., producer is expected
* to release buffer is the same order they were acquired.
*
* @param buf Buffer handle. Must be valid write buffer handle
* for given stream.
*/
void
ReleaseWriteBuffer(SymbianStreamBuffer buf);
/**
* Add event observer for stream. Observers are served in
* first-come-first-serve fashion. That is, newest observer
* is always placed at the end of the chain. If the observer
* is already in the chain, it's popped out and moved to
* the end of the chain.
*
* @param observer Observer (callback function) who should
* be notified when something interesting happens in the stream.
* @param data Additional data to pass to callback function
*
* @return 0 if successful, -1 if stream handle is invalid, -2 if
* OOM situation occurs.
*/
int AddObserver(SymOwfStreamCallback observer,
void* data,MultipleSymbianStreamEventBits aEvents);
/**
* Remove stream event observer. Observer is removed from
* the stream's event nofitication chain and won't receive
* any events from the stream afterwards.
*
* @param observer Observer (callback function)
*
* @param 0 if successful, -1 otherwise
*/
int RemoveObserver(SymOwfStreamCallback observer,
void* aData,MultipleSymbianStreamEventBits aEvents);
/**
* Returns pointer to pixel buffer.
*
* @param buffer Handle of buffer
*/
void*
GetBufferPtrL(SymbianStreamBuffer buffer);
/**
* Undocumented protection flag
*
* @param flag enable disable protection
*/
void
SetProtectionFlag(TBool flag);
TInt BufferHandleToIndex(SymbianStreamBuffer aBuff);
/**
* Add event observer for stream. Observers are served in
* first-come-first-serve fashion. That is, newest observer
* is always placed at the end of the chain.
*
* @param observer Observer (callback function) who should
* be notified when something interesting happens in the stream.
* @aEvent The event corresponding to the observer
* @aScreenNumber The context identifier (screen number)
* @param data Additional data to pass to callback function
*
* @return KErrNone if successful
* KErrArgument if un unknown event is registered
* KErrOverflow if the observer was already registered
* An other system wide error if container couldn't be appended
* OOM situation occurs.
*/
int AddObserver(SymbianStreamCallback aObserver,
TInt32 aEvent,
TInt32 aScreenNumber,
void* aData);
/**
* Remove stream event observer. Observer is removed from
* the stream's event nofitication chain and won't receive
* any events from the stream afterwards.
*
* @param aObserver The callback function
* @param aEvent The event id corresponding to the observer
* @param aScreenNumber The screen number
* @param aData Data must uniquely identify the observer
*
* @param KErrNone if successful, -1 otherwise
* KErrArgument if un unknown event passed as parameter
* KErrNotFount if the event is not found
*/
int RemoveObserver(TInt32 aEvents, void* aData);
/*!
* Notifies the observers not associated with a context.
* The aim is to support legacy SI behavior.
*
* @param aEvent Observer identifier
*
*/
int NotifyObservers(TInt32 aEvent);
/**
* Implements surface content notifications.
*
* When the contents of a surface change, this function gets called
* MCompositionSurfaceUpdate implementation.
*
* @param aSurface The surface that has been updated.
* @param aBuffer The buffer of the surface to be used in
* composition. Integer starting from 0.
* @param aRegion The sub-area that has the updates. If NULL, the
* whole surface is considered changed.
* @param aStatusConsumed A request status object or NULL. If not NULL, then the
* request status is completed once the backend
* does not anymore need the contents of the
* surface to render the update. This may happen
* before actually displaying the finished frame.
* @param aStatusDisplayed This is signaled after the composited frame
* is posted the to display for the first time after
* the update. After this the value in
* aTimeStamp is valid, if the value in the
* status object is KErrNone. Can be NULL, if
* no signal is desired.
* @param aTimeStamp Value of the User::FastCounter() right after the
* display refresh that signaled aStatusDisplayed.
* @param aStatusDispXTimes This is signaled when the surface has been on
* the screen for aDisplayedXTimes refreshes,
* including the update that signaled aStatusDisplayed.
* Can be NULL, if no signal is wanted.
* @param aDisplayedXTimes The number of refreshes after which aStatusDispXTimes
* is signaled or NULL. If values is provided, it must be
* >= 1.
* @param aScreenNumber Uniquelly identifies the context (composer)
*/
void SetNewNotifications(TInt aBuffer,
TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
TRequestStatus* aStatusConsumed, const TRegion* aRegion,
TInt32 aScreenNumber);
/**
* Implements surface content notifications.
*
* When the contents of a surface change, this function gets called
* MCompositionSurfaceUpdate implementation.
*
* @param aSurface The surface that has been updated.
* @param aBuffer The buffer of the surface to be used in
* composition. Integer starting from 0.
* @param aRegion The sub-area that has the updates. If NULL, the
* whole surface is considered changed.
* @param aStatusConsumed A request status object or NULL. If not NULL, then the
* request status is completed once the backend
* does not anymore need the contents of the
* surface to render the update. This may happen
* before actually displaying the finished frame.
* @param aStatusDisplayed This is signaled after the composited frame
* is posted the to display for the first time after
* the update. After this the value in
* aTimeStamp is valid, if the value in the
* status object is KErrNone. Can be NULL, if
* no signal is desired.
* @param aTimeStamp Value of the User::FastCounter() right after the
* display refresh that signaled aStatusDisplayed.
* @param aStatusDispXTimes This is signaled when the surface has been on
* the screen for aDisplayedXTimes refreshes,
* including the update that signaled aStatusDisplayed.
* Can be NULL, if no signal is wanted.
* @param aDisplayedXTimes The number of refreshes after which aStatusDispXTimes
* is signaled or NULL. If values is provided, it must be
* >= 1.
* @param aScreenNumber Uniquelly identifies the context (composer)
*/
void SetAllNotifications(TInt aBuffer,
TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
TRequestStatus* aStatusConsumed, const TRegion* aRegion);
/**
* Process the notifications by accessing the information stored in the observer container.
*
* This method is expected to be called from the observer context every time composer has finished processing
* a stream and the rigger condition is met.
*
* @param aEvent Events map to identify the observer to be processed.
* @param aScreenNumber Screen ID used to identify the target composer that invokes the method
* @param aOperation The Operation expected to be executed
* @param aSerialNumber A number used to identify the composition operation
* @param aReturnMask Parameter to be retrieved by composer, representing the event to be processed
* when composed next time. A new composition is automatically triggered.
*
*/
void ProcessNotifications(TInt32 aEvent, TInt32 aScreenNumber, TInt32 aOperation, TInt32 aSerialNumber, TInt32* aReturnMask);
/**
* A function that checks the validity of the new buffer provided by SUS
*
*
* When the contents of a surface change, this function gets called by the MCompositionSurfaceUpdate implementation.
* If the buffer is invalid all request statuses will be completed with KErrArgument
*
* @param aBuffer The buffer of the surface to be used in
* composition. Integer starting from 0.
* @param aStatusConsumed A request status object or NULL.
* @param aStatusDisplayed A request status object or NULL.
* @param aStatusDispXTimes A request status object or NULL.
*
* @return KErrNone if successful
* KErrArgument if aBuffer parameter is invalid
*
*/
TInt CheckBufferNumber(TInt aBuffer,
TRequestStatus* aStatusDisplayed,
TRequestStatus* aStatusDispXTimes,
TRequestStatus* aStatusConsumed);
private:
/**
* Notifies the composer that the content has been updated.
*
*
* @param aScreenNumber Screen ID used to identify the target composer
* @param aOp The Operation expected the callback to execute
* @param aParam Parameter containing aaditional information to push/pop from targetet composer
*
*/
TBool NotifyComposerContext(TInt32 aScreenNumber, TInt aOp, SYMOWF_CONTENT_UPDATED_PARAM* aParam);
/**
* Notifies the composer that the content is in process to be updated. The composer will have to not access
* observer related information
*
*
* Note that while calling the callback the context update mutex is acquired.
*
* @param aScreenNumber Screen ID used to identify the target composer
* @param aBufferNum The buffer number to be updated
* @param aUpdatedFlags The events that triggers this function call
* @param aRegion The sub-area that has the updates. If NULL, the whole surface is considered changed.
*/
TBool StartUpdateNotifications(TInt aScreenNumber, SYMOWF_CONTENT_UPDATED_PARAM& param);
/**
* Notifies the composer that process of updating the content has finisshed
*
* The composer releases the content mutex and triggers a new composition
*
* @param aScreenNumber Screen ID used to identify the target composer
* @param aBufferNum The buffer number to be updated
* @param aUpdatedFlags The events that triggers this function call
* @param aRegion The sub-area that has the updates. If NULL, the whole surface is considered changed.
*/
TBool EndUpdateNotifications(TInt aScreenNum,
TInt aBufferNum,
TInt32 aUpdatedFlags,
const TRegion* aRegion);
/**
* Notifies the composer that content has been updated
*
* It is used to support old SI behaviour. The content update mutex is acuired
* and released while a new composition is triggered
*
* @param aScreenNumber Screen ID used to identify the target composer
* @param aBufferNum The buffer number to be updated
* @param aUpdatedFlags The events that triggers this function call
* @param aRegion The sub-area that has the updates. If NULL, the whole surface is considered changed.
*/
TBool UpdateNotifications(TInt aScreenNum,
TInt aBufferNum,
TInt32 aUpdatedFlags,
const TRegion* aRegion);
/**
* Processes the available observer
*
* @param aEvent Events map to identify the operation to be executed.
* @param aSerialNumber A number used to identify the composition operation
* @param ContentUpdatedParams Packs the information used when a new request from SUS has to be processed
* @param aCallBackData The observer data stored in the container of observers
* @param aReturnMask Parameter to be retrieved by composer, representing the event to be processed
*/
void Available(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask);
/**
* Processes the available observer
*
* @param aEvent Events map to identify the operation to be executed.
* @param aSerialNumber A number used to identify the composition operation
* @param ContentUpdatedParams Packs the information used when a new request from SUS has to be processed
* @param aCallBackData The observer data stored in the container of observers
* @param aReturnMask Parameter to be retrieved by composer, representing the event to be processed
*/
void Displayed(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask);
/**
* Processes the available observer
*
* @param aEvent Events map to identify the operation to be executed.
* @param aSerialNumber A number used to identify the composition operation
* @param ContentUpdatedParams Packs the information used when a new request from SUS has to be processed
* @param aCallBackData The observer data stored in the container of observers
* @param aReturnMask Parameter to be retrieved by composer, representing the event to be processed
*/
void DisplayedXTimes(TInt32 aEvent, TInt32 aSerialNumber, ContentUpdatedParams* aParams, void* aCallBackData, TInt32* aReturnMask);
/**
* Function used to reset observer data fields
*
* @param aEvent Event identifier for whis the operation is to be executed.
* @param aCallBackData The observer data stored in the container of observers
*/
void ResetCallBackData(void* aCallBackData, TInt32 aEvent);
/**
* Cancels all active notifications by completeting the associated requests
*/
void CancelNotifications();
void SetNotifications(TInt aBuffer,
TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
TRequestStatus* aStatusDispXTimes, TInt* aDisplayedXTimes,
TRequestStatus* aStatusConsumed, const TRegion* aRegion,
TInt32 aScreenNumber, const TNewGlobalNotifications& aGlobalNotifications);
void RequestComplete(TThreadId& aThreadId, TRequestStatus*& aRequestStatus, TInt& aGlobalIndexArray, TInt aStatus);
/**
* Constructor for performing 1st stage construction
*/
CSurfaceStream();
/**
* Symbian's default constructor for performing 2nd stage construction
*/
void ConstructL(const TSurfaceId& aId);
TInt AddNewGlobalNotification(TRequestStatus* aStatusDisplayed, TInt aAssociatedScreens);
void SetReadBufferIndex(TInt aIndex);
TInt GetReadBufferIndex();
TInt GetWriteBufferIndex();
TInt Stride(TInt aWidth, TUidPixelFormat aPixelFormat);
static SymbianStreamBuffer IndexToReadHandle(TInt aIndex);
static SymbianStreamBuffer IndexToWriteHandle(TInt aIndex);
static COpenWfcStreamMap& GetSingletonL();
void SurfaceInfoL(const TSurfaceId& aSurface, RSurfaceManager::TInfoBuf& aInfo);
private:
enum FlippedTarget
{
EFlipNotSet,
EFlippedTargetNormal,
EFlippedTargetFlipped
};
private:
// Each surface buffer has its corresponding TBufferInfo to hold reference count and memory offset
struct TBufferInfo
{
TInt iRefCount;
TInt iOffset;
};
private:
struct TCallBackEntry;
struct TGlobalNotification;
TSurfaceId iSurfaceId; //< Surface ID associated with stream.
TSurfaceId iStreamProxySurfaceId; //< Surface ID generated to represent stream
TInt iRefCount;
RFastLock iRefCountMutex;
TInt iReadBuffer;
RChunk iBufferChunk;
TBufferInfo* iBufferInfo; //< Array of buffer info
RSurfaceManager::TSurfaceInfoV01 iInfo;
static const TInt BUFFER_READ_HANDLE_BASE = 0x100;
static const TInt BUFFER_WRITE_HANDLE_BASE = 0x200;
static const TInt BUFFER_WRITE_UPDATE_OVERWRITE = -1;
TInt iAcquiredWriteBuffer;
TAny* iCallBackHighestPriority;
RArray<TCallBackEntry> iCallBacks;
RFastLock iCallBacksMutex;
TBool iProtected;
RArray<TGlobalNotification> iGlobalNotifications;
TInt iNumberOfScreenAttachedAvailableNotif;
TInt iNumberOfScreenAttachedDisplayedNotif;
TInt iNumberOfScreenAttachedDisplayedXNotif;
FlippedTarget iFlipState;
FlippedTarget iNewFlip;
};
#endif // SURFACESTREAM_H