// Copyright (c) 2007-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:
//
/**
@file
@publishedPartner
@prototype
*/
#ifndef __DISPLAY_CHAN_H__
#define __DISPLAY_CHAN_H__
#include "nk_priv.h"
#include <dispchannel.h>
#include <videodriver.h>
#include "displayhandler.h"
struct TBufferAddressA;
class TScreenBuffer;
/**
Logical Channel kernel side class for Display
*/
class DDisplayChannel : public DLogicalChannel
{
public:
// constants
enum { KDisplayChMajorVersionNumber = 1 };
enum { KDisplayChMinorVersionNumber = 2 };
enum { KDisplayChBuildVersionNumber = 1 };
public:
// Duplicate of RDisplayChannel structure, as the header file cannot be used.
class TCaps
{
public:
TVersion iVersion;
};
class TRequest
{
public:
inline TRequest(void) : iThread(0), iStatus(0) {}
TBool SetStatus(TThreadMessage& aMsg);
void Complete(TInt aResult);
public:
DThread* iThread;
TRequestStatus* iStatus;
};
class TBufferInfo
{
public:
TAny* iAddress;
DChunk* iChunk;
TRequest iRequest;
};
enum TDisplayPanic
{
EDisplayPanicNullThreadOnSet = 1,
EDisplayPanicInUse = 2,
EDisplayPanicThreadAlreadySet = 3,
EDisplayPanicNullThreadOnComplete = 4,
EDisplayPanicThreadOpenFailed = 5,
EDisplayPanicWaitForPostMissed = 6,
EDisplayPanicNullArgument = 7,
EDisplayPanicNotYetImplemented = 8,
EDisplayPanicInvalidDimensions = 9,
EDisplayPanicInvalidRotation = 10,
EDisplayPanicInvalidBitDepth = 11,
EDisplayPanicInvalidStride = 12,
EDisplayPanicInvalidWindowHandle = 13,
EDisplayPanicInvalidFrameBuffers = 14,
EDisplayPanicInvalidRefreshRate = 15,
EDisplayPanicInvalidOffset = 16,
EDisplayPanicNoLegacyBuffer = 17
};
public:
DDisplayChannel(void);
~DDisplayChannel(void);
// DLogicalChannel implementation
virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
virtual void HandleMsg(TMessageBase* aMsg);
// Function used by the UI code to set up the buffers.
virtual TInt Initialize(RDisplayChannel::TDisplayInfo& aInfo,
RDisplayChannel::TDisplayRotation aRotation,
HWND aHwnd, RPointerArray<TAny>& aFrameBuffers,
RPointerArray<TBufferAddressA>& aChunks,
TScreenBuffer& aDsaBuffer,
TSize aResolution,
TSize aTwips,
const RDisplayChannel::TPixelFormat aPixelFormatArray[],
const TInt aPixelFormatArraySize,
const RDisplayChannel::TBufferFormat& aBufferFormat);
virtual void SetLegacyBuffer(void *aAddress);
private:
DDisplayChannel(const DDisplayChannel&);
// Handlers for the three classes of channel message sent
TInt DoControl(TInt aFunction);
void DoRequest(TInt aFunction);
TInt DoCancel(TInt aRequestMask);
TInt NumberOfResolutions();
TInt SafePut(TAny* aDst, TAny* aSrc, TInt aBytes);
void ValidateSpecificInfo(TInt aBytesPerPixel, RDisplayChannel::TOrientationSpecificInfo& aInfo);
static void Panic(TDisplayPanic aPanic);
void ClientPanic(RDisplayChannel::TPanic aPanic);
inline TBool IsCompositionBuffer(RDisplayChannel::TBufferId aId);
static inline TBool IsLegacyBuffer(RDisplayChannel::TBufferId aId);
static inline TBool IsUserBuffer(RDisplayChannel::TBufferId aId);
inline TBool IsValidBuffer(RDisplayChannel::TBufferId aId);
inline RDisplayChannel::TBufferId NextCompositionBuffer(RDisplayChannel::TBufferId aId);
static inline TBool IsFlipped(RDisplayChannel::TDisplayRotation aRotation);
static void VSyncTimerFn(TAny* aDisplayChannel);
void DoVSyncTimer(void);
static void VSyncDfcFn(TAny* aDisplayChannel);
void DoVSync(void);
TInt PostCompositionBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount);
TInt PostLegacyBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount);
TInt GetCompositionBuffer(TAny** aAddress);
TInt PostUserBuffer(RDisplayChannel::TBufferId* aBufferId, TAny* aRegion, RDisplayChannel::TPostCount* aPostCount);
TInt WaitForPost(RDisplayChannel::TPostCount* aPostCount);
TInt WaitForDisplayConnect();
TInt SetRotation(RDisplayChannel::TDisplayRotation* aNewRotation, TBool* aIsBufferPreserved);
TInt RegisterUserBuffer(TInt aChunkHandle, TInt aOffset, RDisplayChannel::TBufferId* aBufferId);
TInt DeregisterUserBuffer(RDisplayChannel::TBufferId* aBufferId);
TInt GetResolutions();
TInt SetResolution(TSize* aSize);
TInt GetResolution(TSize* aSize);
TInt GetTwips(TSize* aSize);
TInt GetIndexForSize(const TSize& aSize,TInt& aSpinnerOut);
TInt GetPixelFormats();
TInt SetBufferFormat(RDisplayChannel::TBufferFormat* aBufferFormat);
TInt NextPlaneOffset(RDisplayChannel::TBufferFormat* aBufferFormat,
RDisplayChannel::TBufferFormatContext* aContext);
TInt NextLineOffset(RDisplayChannel::TBufferFormat* aBufferFormat,
RDisplayChannel::TBufferFormatContext* aContext);
TInt ValidateBufferFormat(const RDisplayChannel::TBufferFormat& aBufferFormat,
const RDisplayChannel::TResolution& aResolution);
private:
// Constants
enum {KDfcPriority = 6};
enum {KBufferNotSet = -1};
// Buffer index points. The legacy buffer is first, followed by the user
// buffers, followed by a variable number of composition buffers.
enum { KLegacyBuffer = 0};
enum { KFirstUserBuffer = KLegacyBuffer + 1};
enum { KFirstCompositionBuffer = KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers};
enum { KMaxBufferSizeHeightAndWidth = KMaxTInt16 };
private:
TInt iScreenNumber;
TThreadMessage* iMsg;
TInt iVSyncTicks; // Number of nanokernel ticks between frames
TUint iNumCompositionBuffers; // Number of composition buffers
TUint iTotalBuffers; // KFirstCompositionBuffer + iNumCompositionBuffers
RDisplayChannel::TDisplayInfo iChannelInfo;
RDisplayChannel::TPostCount iPostCount; // Count of Post... calls
RDisplayChannel::TPostCount iLastPostCount; // Value of iPostCount when last buffer was actually posted
TBufferInfo* iBuffer; // Allocated to contain iTotalBuffers
TBufferAddressA* iChunks;
DThread* iClient;
// Posting support
NTimer iVSync; // Emulated VSync signal using a timer
TDfc iVSyncDfc; // DFC queued on DfcQue0 when iVSync triggers
RDisplayChannel::TBufferId iPostedBuffer; // Index of buffer to be posted on next frame
RDisplayChannel::TDisplayRotation iCurrentRotation; // Rotation of buffer being posted
RDisplayChannel::TDisplayRotation iNewRotation; // Rotation of buffer being posted
TSize iCurrentResolution; // Display resolution (normal rotation) to be posted
TSize iNewResolution; // Display resolution (normal rotation) for buffer being posted
TSize iCurrentTwips;
TInt iPostedRectCount; // Number of rectangles defined in region
RECT iPostedRect[RDisplayChannel::TDisplayInfo::KMaxRectangles]; //
// Paint support
HWND iHwnd; // Window to be painted
RDisplayChannel::TBufferId iDisplayBuffer; // Index of buffer to be painted
RDisplayChannel::TDisplayRotation iDisplayRotation; // Rotation of buffer to be painted
TSize iDisplayResolution; // Display resolution (normal rotation) on screen
// GetCompositionBuffer support
TUint iGetBuffer; // Index of next composition buffer
// WaitForPost support
RDisplayChannel::TPostCount iWaitForPost; // Post count being awaited
TRequest iWaitForPostRequest; // Request to complete when post count reached
// WaitForDisplayConnect support
TRequest iWaitForDisplayConnect; // Request to complete when display connection state changes
TInt iDisplayStateSpinner;
TVersion iVersion;
const RDisplayChannel::TPixelFormat* iPixelFormatArray;
TInt iPixelFormatArraySize;
RDisplayChannel::TBufferFormat iInitialBufferFormat;
RDisplayChannel::TBufferFormat iCurrentBufferFormat;
RDisplayChannel::TBufferFormat iDisplayBufferFormat;
RDisplayChannel::TBufferFormat iNewBufferFormat;
};
inline TBool DDisplayChannel::IsCompositionBuffer(RDisplayChannel::TBufferId aId)
{ return (aId >= KFirstCompositionBuffer && aId < iTotalBuffers); }
inline TBool DDisplayChannel::IsLegacyBuffer(RDisplayChannel::TBufferId aId)
{ return (aId == KLegacyBuffer); }
inline TBool DDisplayChannel::IsUserBuffer(RDisplayChannel::TBufferId aId)
{ return (aId >= KFirstUserBuffer && aId < (KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers)); }
inline TBool DDisplayChannel::IsValidBuffer(RDisplayChannel::TBufferId aId)
{ return (aId >= 0 && aId < iTotalBuffers); }
inline RDisplayChannel::TBufferId DDisplayChannel::NextCompositionBuffer(RDisplayChannel::TBufferId aId)
{ TUint r = (aId + 1); return (r >= iTotalBuffers) ? KFirstCompositionBuffer : r; }
inline TBool DDisplayChannel::IsFlipped(RDisplayChannel::TDisplayRotation aRotation)
{ return !(aRotation & (RDisplayChannel::ERotationNormal | RDisplayChannel::ERotation180)); }
#endif