os/boardsupport/emulator/emulatorbsp/specific/display_chan.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/display_chan.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1554 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +
    1.20 +#include <kernel/kern_priv.h>
    1.21 +#include <kernel/kernel.h>
    1.22 +#include <winsdef.h>
    1.23 +#include <emulator.h>
    1.24 +#include <pixelformats.h>
    1.25 +#include "gui.h"
    1.26 +#include "display_chan.h"
    1.27 +
    1.28 +#define WIN32_LEAN_AND_MEAN
    1.29 +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
    1.30 +#include <windows.h>
    1.31 +#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
    1.32 +
    1.33 +#ifndef DD_TRACE
    1.34 +#ifdef DD_TRACE_ENABLED
    1.35 +#define DD_TRACE(X) X
    1.36 +#else
    1.37 +#define DD_TRACE(X)
    1.38 +#endif
    1.39 +#endif
    1.40 +
    1.41 +
    1.42 +
    1.43 +DDisplayChannel::DDisplayChannel() :
    1.44 +		iVSync(&DDisplayChannel::VSyncTimerFn, this),
    1.45 +		iVSyncDfc(&DDisplayChannel::VSyncDfcFn, this, Kern::DfcQue0(), KDfcPriority),
    1.46 +		iPostedBuffer((TUint)KBufferNotSet),
    1.47 +		iGetBuffer((TUint)KFirstCompositionBuffer),
    1.48 +		iDisplayStateSpinner(0),
    1.49 +		iVersion(KDisplayChMajorVersionNumber, 
    1.50 +			     KDisplayChMinorVersionNumber, 
    1.51 +			     KDisplayChBuildVersionNumber)
    1.52 +	{
    1.53 +	DD_TRACE(Kern::Printf("DDisplayChannel Creation");)
    1.54 +	}
    1.55 +
    1.56 +
    1.57 +DDisplayChannel::~DDisplayChannel()
    1.58 +	{
    1.59 +	DD_TRACE(Kern::Printf("DDisplayChannel Destruction");)
    1.60 +	//clean up.
    1.61 +
    1.62 +	NKern::ThreadEnterCS();
    1.63 +	Kern::Free(iBuffer);
    1.64 +	NKern::ThreadLeaveCS();
    1.65 +
    1.66 +	}
    1.67 +
    1.68 +
    1.69 +/**
    1.70 +  Second stage constructor called by the kernel's device driver framework.
    1.71 +  This is called in the context of the user thread (client) which requested the creation of a Logical Channel
    1.72 +  (E.g. through a call to RBusLogicalChannel::DoCreate)
    1.73 +  The thread is in a critical section.
    1.74 +
    1.75 +  @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
    1.76 +  @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
    1.77 +  @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
    1.78 +
    1.79 +  @return KErrNone if successful, otherwise one of the other system wide error codes.
    1.80 +*/
    1.81 +TInt DDisplayChannel::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
    1.82 +	{
    1.83 +	// Check version
    1.84 +	if (!Kern::QueryVersionSupported(iDevice->iVersion, aVer))
    1.85 +		{
    1.86 +		return KErrNotSupported;
    1.87 +		}
    1.88 +
    1.89 +	iScreenNumber = aUnit;	/*aUnit?*/
    1.90 +	SetDfcQ(Kern::DfcQue0());
    1.91 +	iMsgQ.Receive();
    1.92 +
    1.93 +	// Ask the GUI code to initialize the rest of the object.
    1.94 +	return Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel,
    1.95 +			(TAny*)iScreenNumber, this);
    1.96 +	}
    1.97 +
    1.98 +
    1.99 +void DDisplayChannel::ValidateSpecificInfo(TInt aBytesPerPixel, RDisplayChannel::TOrientationSpecificInfo& aInfo)
   1.100 +	{
   1.101 +	__ASSERT_DEBUG(aInfo.iWidth > 0 && aInfo.iHeight > 0, Panic(EDisplayPanicInvalidDimensions));
   1.102 +	__ASSERT_DEBUG(aInfo.iOffsetBetweenLines > 0, Panic(EDisplayPanicInvalidStride));
   1.103 +	__ASSERT_DEBUG(aInfo.iWidth * aBytesPerPixel <= (TUint)aInfo.iOffsetBetweenLines, Panic(EDisplayPanicInvalidStride));
   1.104 +	
   1.105 +	//this is just to stop compiler complaining..
   1.106 +	(TAny)aBytesPerPixel;
   1.107 +	(TAny)aInfo;
   1.108 +	}
   1.109 +
   1.110 +/**
   1.111 +Finish creating the display channel object.
   1.112 +
   1.113 +@param aInfo			Display description object
   1.114 +@param aRotation		Initial rotation
   1.115 +@param aHwnd			Associated window handle
   1.116 +@param aFrameBuffers	Array of one or more pointers to frame buffers
   1.117 +@param aResolution		Initial resolution
   1.118 +@param aTwips           Size in twips
   1.119 +@return	KErrNone if successful, or a system-wide error otherwise.
   1.120 +*/
   1.121 +TInt DDisplayChannel::Initialize(RDisplayChannel::TDisplayInfo& aInfo, 
   1.122 +		                         RDisplayChannel::TDisplayRotation aRotation,
   1.123 +		                         HWND aHwnd, RPointerArray<TAny>& aFrameBuffers, 
   1.124 +		                         RPointerArray<TBufferAddressA>& aChunks,
   1.125 +								 TScreenBuffer& aDsaBuffer,
   1.126 +		                         TSize aResolution, 
   1.127 +		                         TSize aTwips,
   1.128 +		                         const RDisplayChannel::TPixelFormat aPixelFormatArray[],
   1.129 +								 const TInt aPixelFormatArraySize,
   1.130 +								 const RDisplayChannel::TBufferFormat& aBufferFormat)
   1.131 +
   1.132 +	{
   1.133 +	__ASSERT_DEBUG(aInfo.iBitsPerPixel >= 12 && aInfo.iBitsPerPixel <= 32, Panic(EDisplayPanicInvalidBitDepth));
   1.134 +	__ASSERT_DEBUG(aInfo.iRefreshRateHz > 0, Panic(EDisplayPanicInvalidRefreshRate));
   1.135 +	__ASSERT_DEBUG(aInfo.iAvailableRotations & aRotation, Panic(EDisplayPanicInvalidRotation));
   1.136 +	__ASSERT_DEBUG(aInfo.iNormal.iWidth == aInfo.iFlipped.iHeight, Panic(EDisplayPanicInvalidDimensions));
   1.137 +	__ASSERT_DEBUG(aInfo.iNormal.iHeight == aInfo.iFlipped.iWidth, Panic(EDisplayPanicInvalidDimensions));
   1.138 +	__ASSERT_DEBUG(aRotation == RDisplayChannel::ERotationNormal ||
   1.139 +					aRotation == RDisplayChannel::ERotation90CW ||
   1.140 +					aRotation == RDisplayChannel::ERotation180 ||
   1.141 +					aRotation == RDisplayChannel::ERotation270CW, Panic(EDisplayPanicInvalidRotation));
   1.142 +	__ASSERT_DEBUG(aFrameBuffers.Count() > 0, Panic(EDisplayPanicInvalidFrameBuffers));
   1.143 +	__ASSERT_DEBUG(aHwnd, Panic(EDisplayPanicInvalidWindowHandle));
   1.144 +
   1.145 +	ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iNormal);
   1.146 +	ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iFlipped);
   1.147 +
   1.148 +	// aFrameBuffers includes the legacy buffer at index 0.
   1.149 +	iNumCompositionBuffers = aFrameBuffers.Count() - 1;
   1.150 +	iTotalBuffers = KFirstCompositionBuffer + iNumCompositionBuffers;
   1.151 +	iBuffer = (TBufferInfo*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferInfo));
   1.152 +	iChunks = (TBufferAddressA*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferAddressA));
   1.153 +	if (!iBuffer)
   1.154 +		{
   1.155 +		return KErrNoMemory;
   1.156 +		}
   1.157 +
   1.158 +	aInfo.iNumCompositionBuffers = iNumCompositionBuffers;
   1.159 +	for (TUint index = 0; index < iNumCompositionBuffers; index++)
   1.160 +		{
   1.161 +		iBuffer[index + KFirstCompositionBuffer].iAddress = aFrameBuffers[index + 1];
   1.162 +		iChunks[index + KFirstCompositionBuffer].iChunk = aChunks[index + 1]->iChunk;
   1.163 +		}
   1.164 +		
   1.165 +	iChannelInfo = aInfo;
   1.166 +	
   1.167 +	iDisplayRotation = iCurrentRotation = aRotation;
   1.168 +	iDisplayResolution = iCurrentResolution = aResolution;
   1.169 +	iCurrentTwips = aTwips;
   1.170 +	iHwnd = aHwnd;
   1.171 +	
   1.172 +	// Ensure the VSync DFC is on the same queue as the message handling.
   1.173 +	iVSyncTicks = NKern::TimerTicks(1000 / aInfo.iRefreshRateHz);
   1.174 +    iVSync.OneShot(iVSyncTicks);
   1.175 +
   1.176 +	if (aDsaBuffer.iMemChunks.Count() != 0)
   1.177 +		{	
   1.178 +		iBuffer[KLegacyBuffer].iAddress = aDsaBuffer.iFrameBuffers[0];
   1.179 +		}
   1.180 +	else
   1.181 +		{
   1.182 +		iBuffer[KLegacyBuffer].iAddress = NULL;
   1.183 +		}
   1.184 +    
   1.185 +	iPixelFormatArray = aPixelFormatArray;
   1.186 +	iPixelFormatArraySize = aPixelFormatArraySize;
   1.187 +
   1.188 +	// copy the initial buffer format
   1.189 +	iInitialBufferFormat = aBufferFormat;
   1.190 +	iDisplayBufferFormat = iInitialBufferFormat;
   1.191 +	iCurrentBufferFormat = iDisplayBufferFormat;
   1.192 +	return KErrNone;
   1.193 +	}
   1.194 +
   1.195 +
   1.196 +/**
   1.197 +Set the address of the legacy buffer. 
   1.198 + 
   1.199 +@param aAddress			Pointer to the legacy buffer. 
   1.200 +*/
   1.201 +void DDisplayChannel::SetLegacyBuffer(void *aAddress)
   1.202 +	{ 
   1.203 +	iBuffer[KLegacyBuffer].iAddress = aAddress;
   1.204 +	}
   1.205 +
   1.206 +
   1.207 +
   1.208 +/**
   1.209 +Handle a message on this display for the logical channel.
   1.210 +
   1.211 +@param aMsg	The message to process. The iValue member of this distinguishes the
   1.212 +		message type:
   1.213 +		iValue == ECloseMsg, channel close message
   1.214 +		iValue == KMaxTInt, a 'DoCancel' message
   1.215 +		iValue >= 0, a 'DoControl' message with function number equal to iValue
   1.216 +		iValue < 0, a 'DoRequest' message with function number equal to ~iValue
   1.217 +*/
   1.218 +void DDisplayChannel::HandleMsg(TMessageBase* aMsg)
   1.219 +	{
   1.220 +	iMsg = (TThreadMessage*)aMsg;
   1.221 +	TInt id = iMsg->iValue;
   1.222 +	TInt r = KErrNone;
   1.223 +
   1.224 +    if (id == (TInt)ECloseMsg)
   1.225 +       {
   1.226 +       iVSync.Cancel();
   1.227 +	   iWaitForPostRequest.Complete(KErrCancel);
   1.228 +	   iWaitForDisplayConnect.Complete(KErrCancel);
   1.229 +       if (iBuffer)
   1.230 +	       	{
   1.231 +    		// Unhook display channel from the GUI code if initialized.
   1.232 +    		if (iBuffer[KLegacyBuffer].iAddress)
   1.233 +	       		{
   1.234 +    		      	Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel,
   1.235 +	   					(TAny*)iScreenNumber, NULL);
   1.236 +        	   		PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0, 0);
   1.237 +		      	    InvalidateRect(iHwnd, NULL, FALSE);
   1.238 +    			}
   1.239 +
   1.240 +	       	RDisplayChannel::TBufferId index = iTotalBuffers;
   1.241 +
   1.242 +    		while (index-- > 0)
   1.243 +	       		{
   1.244 +		          	iBuffer[index].iRequest.Complete(KErrCancel);
   1.245 +
   1.246 +        			if (IsUserBuffer(index))
   1.247 +		          		{
   1.248 +        				// Close chunk
   1.249 +		          		if (iBuffer[index].iChunk)
   1.250 +        					{
   1.251 +		              			NKern::ThreadEnterCS();
   1.252 +            					Kern::ChunkClose(iBuffer[index].iChunk);
   1.253 +            					NKern::ThreadLeaveCS();
   1.254 +        					}
   1.255 +				        }
   1.256 +			     }
   1.257 +
   1.258 +            }
   1.259 +			iMsg->Complete(KErrNone, EFalse);
   1.260 +			return;
   1.261 +        }
   1.262 +
   1.263 +	if (id < 0)
   1.264 +		{
   1.265 +		DoRequest(~id);
   1.266 +		r = KErrNone;
   1.267 +		}
   1.268 +	else
   1.269 +		{
   1.270 +		r = (id == KMaxTInt) ? DoCancel(iMsg->Int0()) : DoControl(id);
   1.271 +		}
   1.272 +
   1.273 +	iMsg->Complete(r, (id != ECloseMsg));
   1.274 +	}
   1.275 +
   1.276 +
   1.277 +/**
   1.278 +Process synchronous 'control' requests. Parameters are in the first two
   1.279 +arguments of iMsg.
   1.280 +*/
   1.281 +TInt DDisplayChannel::DoControl(TInt aFunction)
   1.282 +	{
   1.283 +	DD_TRACE(Kern::Printf(">DDisplayChannel::DoControl fn=%d\n", aFunction);)
   1.284 +
   1.285 +	TInt r = KErrNotSupported;
   1.286 +	TPckgBuf<RDisplayChannel::TDisplayInfo> pkg(iChannelInfo);
   1.287 +	switch(aFunction)
   1.288 +		{
   1.289 +		case RDisplayChannel::ECtrlGetDisplayInfo:
   1.290 +			// a1: TDisplayInfo* info [out]
   1.291 +			Kern::KUDesPut(*(TDes8*)iMsg->Ptr0(), pkg); ///*&iChannelInfo*/);
   1.292 +			r = KErrNone;
   1.293 +			break;
   1.294 +
   1.295 +		case RDisplayChannel::ECtrlOpen:
   1.296 +			// Everything is done in Construct
   1.297 +			r = KErrNone;
   1.298 +			break;
   1.299 +
   1.300 +		case RDisplayChannel::ECtrlClose:
   1.301 +			// Nothing to do?
   1.302 +			r = KErrNone;
   1.303 +			break;
   1.304 +
   1.305 +		case RDisplayChannel::ECtrlPostCompositionBuffer:
   1.306 +			// a1: const TRegionFix<KMaxRectangles>* region [in]
   1.307 +			// a2: TPostCount* post count [out]
   1.308 +			r = PostCompositionBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1());
   1.309 +			break;
   1.310 +
   1.311 +		case RDisplayChannel::ECtrlPostLegacyBuffer:
   1.312 +			// a1: const TRegionFix<KMaxRectangles>* region [in]
   1.313 +			// a2: TPostCount* post count [out]
   1.314 +			r = PostLegacyBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1());
   1.315 +			break;
   1.316 +
   1.317 +		case RDisplayChannel::ECtrlRegisterUserBuffer:
   1.318 +			// a1: { TInt Chunk handle, TInt offset }* [in]
   1.319 +			// a2: TInt* buffer ID [out]
   1.320 +			{
   1.321 +			__ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
   1.322 +			TInt arg[2];
   1.323 +			kumemget(arg, iMsg->Ptr0(), sizeof(arg));
   1.324 +			r = RegisterUserBuffer(arg[0], arg[1], (RDisplayChannel::TBufferId*)iMsg->Ptr1());
   1.325 +			}
   1.326 +			break;
   1.327 +
   1.328 +		case RDisplayChannel::ECtrlDeregisterUserBuffer:
   1.329 +			// a1: TBufferId* buffer ID [in]
   1.330 +			r = DeregisterUserBuffer((RDisplayChannel::TBufferId*)iMsg->Ptr0());
   1.331 +			break;
   1.332 +
   1.333 +		case RDisplayChannel::ECtrlSetRotation:
   1.334 +			// a1: TDisplayRotation* new rotation [in]
   1.335 +			// a2: TBool* display config has changed [out]
   1.336 +			r = SetRotation((RDisplayChannel::TDisplayRotation*)iMsg->Ptr0(), (TBool*)iMsg->Ptr1());
   1.337 +			break;
   1.338 +
   1.339 +		case RDisplayChannel::ECtrlCurrentRotation:
   1.340 +			// a1: TDisplayRotation* current rotation [out]
   1.341 +			r = SafePut(iMsg->Ptr0(), &iCurrentRotation, sizeof(iCurrentRotation));
   1.342 +			break;
   1.343 +
   1.344 +		case ECloseMsg:
   1.345 +			r = KErrNone;
   1.346 +			break;
   1.347 +
   1.348 +	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:
   1.349 +    	    {
   1.350 +    	    TInt arg[2];
   1.351 +    	    TInt index = *((TInt*)(iMsg->Ptr0()));
   1.352 +            r = Kern::MakeHandleAndOpen(iMsg->Client(), iChunks[index + KFirstCompositionBuffer].iChunk);
   1.353 +            if(r >= 0)
   1.354 +                {
   1.355 +	            arg[0] = r;
   1.356 +	            arg[1] = 0;
   1.357 +				SafePut(iMsg->Ptr1(),&arg,(sizeof(TInt)*2));
   1.358 +                r = KErrNone;
   1.359 +                }
   1.360 +             }
   1.361 +    	    break;
   1.362 +    	 // added to v1.0
   1.363 +	    case RDisplayChannel::ECtrlVersion:
   1.364 +			r = SafePut(iMsg->Ptr0(), &iVersion, sizeof(iVersion));
   1.365 +	    	break;
   1.366 +    	//v1_1
   1.367 +	    case RDisplayChannel::ECtrlNumberOfResolutions:
   1.368 +	    	{
   1.369 +	    	r = NumberOfResolutions();
   1.370 +	    	}
   1.371 +	    	break;
   1.372 +	    case RDisplayChannel::ECtrlGetResolutions:
   1.373 +	    	{
   1.374 +	    	r = GetResolutions();
   1.375 +	    	if(r == KErrCorrupt) //Resolution list changed during GetResolutions
   1.376 +	    		{//second go
   1.377 +	    		r = GetResolutions();
   1.378 +	    		}
   1.379 +	    	}
   1.380 +	    	break;
   1.381 +	    case RDisplayChannel::ECtrlSetResolution:
   1.382 +	    	{
   1.383 +	    	r = SetResolution((TSize*)iMsg->Ptr0());
   1.384 +	    	}
   1.385 +	    	break;
   1.386 +	    case RDisplayChannel::ECtrlGetResolution:
   1.387 +	    	{
   1.388 +	    	r = GetResolution((TSize*)iMsg->Ptr0());
   1.389 +	    	}
   1.390 +	    	break;
   1.391 +	    case RDisplayChannel::ECtrlGetTwips:
   1.392 +	    	{
   1.393 +	    	r = GetTwips((TSize*)iMsg->Ptr0());
   1.394 +	    	}
   1.395 +	    	break;
   1.396 +	    case RDisplayChannel::ECtrlNumberOfPixelFormats:
   1.397 +			r = iPixelFormatArraySize;
   1.398 +	    	break;
   1.399 +	    case RDisplayChannel::ECtrlGetPixelFormats:
   1.400 +	    	r = GetPixelFormats();
   1.401 +	    	break;
   1.402 +	    case RDisplayChannel::ECtrlSetBufferFormat:
   1.403 +	    	r = SetBufferFormat((RDisplayChannel::TBufferFormat*)iMsg->Ptr0());
   1.404 +	    	break;
   1.405 +	    case RDisplayChannel::ECtrlGetBufferFormat:
   1.406 +			r = SafePut(iMsg->Ptr0(), &iCurrentBufferFormat, sizeof(iCurrentBufferFormat));
   1.407 +	    	break;
   1.408 +	    case RDisplayChannel::ECtrlNextPlaneOffset:
   1.409 +	    	// we support, for moment only packed pixel formats
   1.410 +	    	r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL);
   1.411 +	    	break;
   1.412 +	    case RDisplayChannel::ECtrlNextLineOffset:
   1.413 +	    	// use the internal current resolution and current rotation
   1.414 +	    	r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL);
   1.415 +	    	break;
   1.416 +	    case RDisplayChannel::ECtrlNextPlaneOffsetExtended:
   1.417 +	    	// we support, for moment only packed pixel formats
   1.418 +	    	r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(),
   1.419 +	    			            (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1());
   1.420 +	    	break;
   1.421 +	    case RDisplayChannel::ECtrlNextLineOffsetExtended:
   1.422 +	    	r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(),
   1.423 +	    			           (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1());
   1.424 +	    	break;
   1.425 +		}
   1.426 +	DD_TRACE(Kern::Printf("<DDisplayChannel::DoControl result=%d\n",r);)
   1.427 +	return r;
   1.428 +	}
   1.429 +
   1.430 +TInt DDisplayChannel::GetIndexForSize(const TSize& aSize,TInt& aSpinnerOut)
   1.431 +	{
   1.432 +	TInt numberOfResolutions = 0;
   1.433 +	TInt spinner1 = 0;
   1.434 +	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &spinner1, iScreenNumber);
   1.435 +	if(r < KErrNone)
   1.436 +		return r;
   1.437 +	TVideoInfoV01 info;
   1.438 +	TPckg<TVideoInfoV01> infoPckg(info);
   1.439 +
   1.440 +	for (TInt res=0;res<numberOfResolutions;res++)
   1.441 +		{
   1.442 +		//pass info package to be filled in, also sending the config to read, and the screen within that
   1.443 +		Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, (TAny*)&res, (TAny*)&infoPckg, iScreenNumber);
   1.444 +		if (info.iSizeInPixels.iWidth==aSize.iWidth && info.iSizeInPixels.iHeight==aSize.iHeight)
   1.445 +			{
   1.446 +			r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &aSpinnerOut, iScreenNumber);
   1.447 +			if(r < KErrNone)
   1.448 +				return r;
   1.449 +			if (aSpinnerOut!=spinner1)
   1.450 +				{
   1.451 +				return KErrCorrupt;
   1.452 +				}
   1.453 +			else
   1.454 +				{
   1.455 +				return res;
   1.456 +				}
   1.457 +			}
   1.458 +		}
   1.459 +	return KErrArgument;
   1.460 +	}
   1.461 +
   1.462 +/**
   1.463 +Process asynchronous requests. TRequestStatus is at iMsg->Ptr0(), and the other
   1.464 +two parameters are in iMsg->Ptr1() and iMsg->Ptr2().
   1.465 +*/
   1.466 +void DDisplayChannel::DoRequest(TInt aFunction)
   1.467 +	{
   1.468 +	DD_TRACE(Kern::Printf(">DDisplayChannel::DoRequest fn=%d\n", aFunction);)
   1.469 +
   1.470 +	TInt r = KErrNotSupported;
   1.471 +
   1.472 +	switch(aFunction)
   1.473 +		{
   1.474 +		case RDisplayChannel::EReqGetCompositionBuffer:
   1.475 +			// a1: TAny** buffer address [out]
   1.476 +			r = GetCompositionBuffer(static_cast<TAny**>(iMsg->Ptr1()));
   1.477 +			break;
   1.478 +
   1.479 +		case RDisplayChannel::EReqPostUserBuffer:
   1.480 +			// a1: { TBufferId* buffer ID, const TRegionFix<KMaxRectangles>* region }* [in]
   1.481 +			// a2: TPostCount* post count [out]
   1.482 +			{
   1.483 +			TAny* arg[2];
   1.484 +			__ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
   1.485 +			kumemget(arg, iMsg->Ptr1(), sizeof(arg));
   1.486 +			r = PostUserBuffer(reinterpret_cast<RDisplayChannel::TBufferId*>(arg[0]), arg[1],
   1.487 +					reinterpret_cast<RDisplayChannel::TPostCount*>(iMsg->Ptr2()));
   1.488 +			}
   1.489 +			break;
   1.490 +
   1.491 +		case RDisplayChannel::EReqWaitForPost:
   1.492 +			// a1: TInt* post to wait for [in]
   1.493 +			r = WaitForPost(static_cast<RDisplayChannel::TPostCount*>(iMsg->Ptr1()));
   1.494 +			break;
   1.495 +	    	//v1_1
   1.496 +		case RDisplayChannel::EReqWaitForDisplayConnect:
   1.497 +			r = WaitForDisplayConnect();
   1.498 +			break;
   1.499 +		}
   1.500 +
   1.501 +	DD_TRACE(Kern::Printf("<DDisplayChannel::DoRequest result=%d\n",r);)
   1.502 +
   1.503 +	if (r != KRequestPending)
   1.504 +		{
   1.505 +		TRequestStatus* status = reinterpret_cast<TRequestStatus*>(iMsg->Ptr0());
   1.506 +		Kern::RequestComplete(iMsg->Client(), status, r);
   1.507 +		}
   1.508 +	}
   1.509 +
   1.510 +
   1.511 +/**
   1.512 +Process asynchronous request cancellations
   1.513 +*/
   1.514 +TInt DDisplayChannel::DoCancel(TInt aRequestMask)
   1.515 +	{
   1.516 +	DD_TRACE(Kern::Printf(">DDisplayChannel::DoCancel mask=%x\n", aRequestMask);)
   1.517 +
   1.518 +	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelGetCompositionBuffer))
   1.519 +		{
   1.520 +		if (IsCompositionBuffer(iGetBuffer))
   1.521 +			{
   1.522 +			iBuffer[iGetBuffer].iRequest.Complete(KErrCancel);
   1.523 +			}
   1.524 +		}
   1.525 +
   1.526 +	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelPostUserBuffer))
   1.527 +		{
   1.528 +		if (IsUserBuffer(iPostedBuffer))
   1.529 +			{
   1.530 +			iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
   1.531 +			}
   1.532 +		}
   1.533 +
   1.534 +	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForPost))
   1.535 +		{
   1.536 +		iWaitForPostRequest.Complete(KErrCancel);
   1.537 +		}
   1.538 +	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForDisplayConnect))
   1.539 +		{
   1.540 +		iWaitForDisplayConnect.Complete(KErrCancel);
   1.541 +		}
   1.542 +
   1.543 +	DD_TRACE(Kern::Printf("<DDisplayChannel::DoCancel\n",r);)
   1.544 +	return KErrNone;
   1.545 +	}
   1.546 +
   1.547 +
   1.548 +/**
   1.549 +Get the number of resolutions on this screen
   1.550 +@return Number of resolutions if successful, otherwise a system wide error code.
   1.551 +*/
   1.552 +TInt DDisplayChannel::NumberOfResolutions()
   1.553 +	{
   1.554 +	TInt numberOfResolutions = 0;
   1.555 +	TInt error = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber);
   1.556 +	if (error != KErrNone)
   1.557 +		{
   1.558 +		return error;
   1.559 +		}
   1.560 +	return numberOfResolutions;
   1.561 +	}
   1.562 +
   1.563 +
   1.564 +/**
   1.565 +Safely write from kernel to user memory.
   1.566 +@param aDst	Pointer to destination, user memory.
   1.567 +@param aSrc	Pointer to source, kernel memory.
   1.568 +@param aBytes	Number of bytes to write.
   1.569 +@return KErrNone if successful, KErrArgument if either pointer is NULL.
   1.570 +*/
   1.571 +TInt DDisplayChannel::SafePut(TAny* aDst, TAny* aSrc, TInt aBytes)
   1.572 +	{
   1.573 +	if (!aDst || !aSrc)
   1.574 +		{
   1.575 +		return KErrArgument;
   1.576 +		}
   1.577 +
   1.578 +	kumemput(aDst, aSrc, aBytes);
   1.579 +	return KErrNone;
   1.580 +	}
   1.581 +
   1.582 +
   1.583 +/**
   1.584 +Driver panic.
   1.585 +@param	aPanic	The cause of the panic.
   1.586 +*/
   1.587 +void DDisplayChannel::Panic(TDisplayPanic aPanic)
   1.588 +	{
   1.589 +	Kern::Fault("DISPLAY", aPanic);
   1.590 +	}
   1.591 +
   1.592 +
   1.593 +/**
   1.594 +Client panic.
   1.595 +@param	aPanic	The cause of the panic.
   1.596 +*/
   1.597 +void DDisplayChannel::ClientPanic(RDisplayChannel::TPanic aPanic)
   1.598 +	{
   1.599 +	_LIT(KLitDisplayChannel, "DISPLAYCHANNEL");
   1.600 +	Kern::ThreadKill(iClient, EExitPanic, aPanic, KLitDisplayChannel);
   1.601 +	}
   1.602 +
   1.603 +
   1.604 +/**
   1.605 +VSync is emulated by using a nanokernel timer to call this function at the
   1.606 +frame rate.
   1.607 +*/
   1.608 +void DDisplayChannel::VSyncTimerFn(TAny* aDisplayChannel)
   1.609 +	{
   1.610 +	reinterpret_cast<DDisplayChannel*>(aDisplayChannel)->DoVSyncTimer();
   1.611 +	}
   1.612 +
   1.613 +/**
   1.614 +Instance function called on the timer thread. Queues the VSyncDfc to run on its
   1.615 +thread.
   1.616 +*/
   1.617 +void DDisplayChannel::DoVSyncTimer(void)
   1.618 +	{
   1.619 +	iVSyncDfc.Add();
   1.620 +	iVSync.Again(iVSyncTicks);
   1.621 +	}
   1.622 +
   1.623 +
   1.624 +/**
   1.625 +DFC function to post the current buffer to the display.
   1.626 +@param aDisplayImpl	The display object to be posted.
   1.627 +*/
   1.628 +void DDisplayChannel::VSyncDfcFn(TAny* aDisplayChannel)
   1.629 +	{
   1.630 +	reinterpret_cast<DDisplayChannel*>(aDisplayChannel)->DoVSync();
   1.631 +	}
   1.632 +
   1.633 +
   1.634 +/**
   1.635 +Post the current buffer to the display. Signal waiting threads under various
   1.636 +conditions. This is run off the same DFC queue as message handling, so there is
   1.637 +no need to protect the fields.
   1.638 +*/
   1.639 +void DDisplayChannel::DoVSync(void)
   1.640 +	{
   1.641 +	if(iWaitForDisplayConnect.iStatus)
   1.642 +		{
   1.643 +		TInt currentSpinner;
   1.644 +		Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &currentSpinner, NULL, iScreenNumber);
   1.645 +		//display state changed
   1.646 +		if(currentSpinner != iDisplayStateSpinner)
   1.647 +			iWaitForDisplayConnect.Complete(KErrNone);
   1.648 +		}
   1.649 +		
   1.650 +	if (IsValidBuffer(iPostedBuffer))
   1.651 +		{
   1.652 +		// Complete any outstanding request for the buffer which was displayed.
   1.653 +		// This either signifies the user or composition buffer becoming
   1.654 +		// available 
   1.655 +		if (iDisplayBuffer != iPostedBuffer)
   1.656 +			{
   1.657 +			iBuffer[iDisplayBuffer].iRequest.Complete(KErrNone);
   1.658 +			}
   1.659 +
   1.660 +		iDisplayBuffer = (RDisplayChannel::TBufferId)iPostedBuffer;
   1.661 +		iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet;
   1.662 +
   1.663 +		// Update the pixel pointer used when painting the client window		
   1.664 +		PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0,
   1.665 +				(LPARAM)iBuffer[iDisplayBuffer].iAddress);
   1.666 +
   1.667 +		// check if the buffer format is modified
   1.668 +	if ((iDisplayBufferFormat.iSize.iHeight != iNewBufferFormat.iSize.iHeight) || 
   1.669 +		(iDisplayBufferFormat.iSize.iWidth != iNewBufferFormat.iSize.iWidth) ||
   1.670 +		(iDisplayBufferFormat.iPixelFormat != iNewBufferFormat.iPixelFormat))
   1.671 +		{
   1.672 +		// We post in one messages everything, but we got to pack the size
   1.673 +		// speculate that the maximum width and height can be represented in 16 bit
   1.674 +		TUint aggregateSize = ((TUint)iNewBufferFormat.iSize.iHeight << 16) & 0xffff0000; 
   1.675 +		aggregateSize += (TUint)iNewBufferFormat.iSize.iWidth & 0x0000ffff;
   1.676 +		PostMessage(iHwnd, 
   1.677 +				    WMU_SET_BUFFER_FORMAT, 
   1.678 +				    aggregateSize, 
   1.679 +				    iNewBufferFormat.iPixelFormat);
   1.680 +		iDisplayBufferFormat = iNewBufferFormat;
   1.681 +		}
   1.682 +	
   1.683 +		if (iDisplayRotation != iNewRotation)
   1.684 +			{
   1.685 +			iDisplayRotation = iNewRotation;
   1.686 +
   1.687 +			TUint flip;
   1.688 +			switch (iDisplayRotation)
   1.689 +				{
   1.690 +				case RDisplayChannel::ERotation90CW:
   1.691 +					flip = EEmulatorFlipLeft;
   1.692 +					break;
   1.693 +				case RDisplayChannel::ERotation180:
   1.694 +					flip = EEmulatorFlipInvert;
   1.695 +					break;
   1.696 +				case RDisplayChannel::ERotation270CW:
   1.697 +					flip = EEmulatorFlipRight;
   1.698 +					break;
   1.699 +				default:	// Normal
   1.700 +					flip = EEmulatorFlipRestore;
   1.701 +					break;
   1.702 +				}
   1.703 +			PostMessage(iHwnd, WM_FLIP_MESSAGE, flip, NULL);
   1.704 +
   1.705 +			iPostedRectCount = 0;	// Force full invalidation
   1.706 +			}
   1.707 +
   1.708 +		if (iDisplayResolution.iWidth != iNewResolution.iWidth ||
   1.709 +				iDisplayResolution.iHeight != iNewResolution.iHeight)
   1.710 +			{
   1.711 +			iDisplayResolution = iNewResolution;
   1.712 +			PostMessage(iHwnd, WMU_SET_DISPLAY_SIZE, 
   1.713 +					iDisplayResolution.iWidth, iDisplayResolution.iHeight);
   1.714 +			}
   1.715 +	
   1.716 +		
   1.717 +		// Invalidate the window contents where necessary
   1.718 +		TInt count = iPostedRectCount;
   1.719 +		if (count)
   1.720 +			{
   1.721 +			// Order of invalidation is immaterial
   1.722 +			while (count--)
   1.723 +				{
   1.724 +				InvalidateRect(iHwnd, &iPostedRect[count], FALSE);
   1.725 +				}
   1.726 +
   1.727 +			iPostedRectCount = 0;
   1.728 +			}
   1.729 +		else
   1.730 +			{
   1.731 +			InvalidateRect(iHwnd, NULL, FALSE);
   1.732 +			}
   1.733 +
   1.734 +		// Use differences to allow for wraparound
   1.735 +		if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0)
   1.736 +			{
   1.737 +			// Post waited for is now being displayed or was dropped
   1.738 +			iWaitForPostRequest.Complete(KErrNone);
   1.739 +			}
   1.740 +		iLastPostCount = iPostCount;
   1.741 +		}
   1.742 +	}
   1.743 +
   1.744 +
   1.745 +/**
   1.746 +Set the status object for this request and the thread to complete it on, if not
   1.747 +already set.
   1.748 +@param aStatus	The new request status.
   1.749 +@param aThread	The thread on which to complete.
   1.750 +@return EFalse if the status is already set, or ETrue if the status has now been
   1.751 +set.
   1.752 +*/
   1.753 +TBool DDisplayChannel::TRequest::SetStatus(TThreadMessage& aMsg)
   1.754 +	{
   1.755 +	if (iStatus)
   1.756 +		{
   1.757 +		__ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnSet));
   1.758 +		return EFalse;	// In use
   1.759 +		}
   1.760 +
   1.761 +	__ASSERT_DEBUG(!iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadAlreadySet));
   1.762 +	DThread* thread = aMsg.Client();
   1.763 +	TInt r = thread->Open();
   1.764 +	__ASSERT_DEBUG( r == KErrNone, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadOpenFailed));
   1.765 +	(TAny)r;
   1.766 +	iThread = thread;
   1.767 +	iStatus = reinterpret_cast<TRequestStatus*>(aMsg.Ptr0());
   1.768 +	return ETrue;
   1.769 +	}
   1.770 +
   1.771 +
   1.772 +/**
   1.773 +Complete the request with the given result. If the status has not been set, or
   1.774 +has already been completed, this does nothing.
   1.775 +@param aResult	The result of the asynchronous request.
   1.776 +*/
   1.777 +void DDisplayChannel::TRequest::Complete(TInt aResult)
   1.778 +	{
   1.779 +	if (iStatus)
   1.780 +		{
   1.781 +    	__ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnComplete));
   1.782 +		Kern::RequestComplete(iThread, iStatus, aResult);
   1.783 +		Kern::SafeClose((DObject*&)iThread, NULL);
   1.784 +		}
   1.785 +	}
   1.786 +
   1.787 +
   1.788 +/**
   1.789 +Post the current composition buffer to the display on the next frame tick.
   1.790 +@param aRegion	NULL if the entire buffer has changed, or a user pointer to up
   1.791 +to TDisplayInfo::KMaxRectagles areas that have changed.
   1.792 +@param aPostCount	User pointer to an integer to receive the new post count.
   1.793 +@return KErrNone, or a system-wide error code
   1.794 +*/
   1.795 +TInt DDisplayChannel::PostCompositionBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
   1.796 +	{
   1.797 +	if (!IsCompositionBuffer(iGetBuffer))
   1.798 +		{
   1.799 +		return KErrNotSupported;
   1.800 +		}
   1.801 +
   1.802 +	if (iWaitForPost == iPostCount)
   1.803 +		{
   1.804 +		// Complete wait for post (dropped)
   1.805 +		iWaitForPostRequest.Complete(KErrNone);
   1.806 +		}
   1.807 +
   1.808 +	if (IsUserBuffer(iPostedBuffer))
   1.809 +		{
   1.810 +		// Complete the user post request (not displayed)
   1.811 +		iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
   1.812 +		}
   1.813 +
   1.814 +	iPostedBuffer = iGetBuffer;
   1.815 +	iGetBuffer = NextCompositionBuffer(iGetBuffer);
   1.816 +
   1.817 +	if (iNumCompositionBuffers > 2 && iGetBuffer == iDisplayBuffer)
   1.818 +		{
   1.819 +		// With more than two buffers, there must always be one available with
   1.820 +		// no waiting required, so find it.
   1.821 +		iGetBuffer = NextCompositionBuffer(iGetBuffer);
   1.822 +		}
   1.823 +
   1.824 +	// Get the region
   1.825 +	if (aRegion)
   1.826 +		{
   1.827 +		// Set iPostedRect(Count) from aRegion.
   1.828 +		Panic(EDisplayPanicNotYetImplemented);
   1.829 +		}
   1.830 +
   1.831 +	// What to do about wrapping?
   1.832 +	iPostCount++;
   1.833 +	iNewRotation = iCurrentRotation;
   1.834 +	iNewResolution = iCurrentResolution;
   1.835 +	iNewBufferFormat = iCurrentBufferFormat;
   1.836 +	SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
   1.837 +
   1.838 +	return KErrNone;
   1.839 +	}
   1.840 +
   1.841 +
   1.842 +/**
   1.843 +Post the legacy buffer to the display on the next frame tick.
   1.844 +@param aRegion	NULL if the entire buffer has changed, or a user pointer to up
   1.845 +to TDisplayInfo::KMaxRectagles areas that have changed.
   1.846 +@param aPostCount	User pointer to an integer to receive the new post count.
   1.847 +@return KErrNone, or a system-wide error code
   1.848 +*/
   1.849 +TInt DDisplayChannel::PostLegacyBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
   1.850 +	{
   1.851 +	if (iWaitForPost == iPostCount)
   1.852 +		{
   1.853 +		// Complete wait for post (dropped)
   1.854 +		iWaitForPostRequest.Complete(KErrNone);
   1.855 +		}
   1.856 +
   1.857 +	if (IsUserBuffer(iPostedBuffer))
   1.858 +		{
   1.859 +		iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
   1.860 +		}
   1.861 +
   1.862 +	// iBuffer should NOT be NULL here!
   1.863 +	__ASSERT_ALWAYS(iBuffer[KLegacyBuffer].iAddress, Panic(EDisplayPanicNoLegacyBuffer));
   1.864 +	iPostedBuffer = KLegacyBuffer;
   1.865 +
   1.866 +	// Get the region into iRegion
   1.867 +	if (aRegion)
   1.868 +		{
   1.869 +		// Set iPostedRect(Count) from aRegion.
   1.870 +		Panic(EDisplayPanicNotYetImplemented);
   1.871 +		}
   1.872 +
   1.873 +	iPostCount++;
   1.874 +	iNewRotation = iCurrentRotation;
   1.875 +	iNewResolution = iCurrentResolution;
   1.876 +	iNewBufferFormat = iCurrentBufferFormat;
   1.877 +	SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
   1.878 +
   1.879 +	return KErrNone;
   1.880 +	}
   1.881 +
   1.882 +
   1.883 +/**
   1.884 +Asynchronously request the current composition buffer. Completes immediately
   1.885 +if not already being displayed, or an error occurs.
   1.886 +@param aStatus	The request status to be completed.
   1.887 +@param aAddress	The user pointer to the location to put the address.
   1.888 +*/
   1.889 +TInt DDisplayChannel::GetCompositionBuffer(TAny** aAddress)
   1.890 +	{
   1.891 +	if (!IsCompositionBuffer(iGetBuffer))
   1.892 +		{
   1.893 +		// No composition buffers available for use.
   1.894 +		return KErrNotSupported;
   1.895 +		}
   1.896 +
   1.897 +	// The address won't change, so may as well set it now.
   1.898 +	TUint idx = iGetBuffer - KFirstCompositionBuffer;
   1.899 +	if (SafePut(aAddress, &idx, sizeof(TUint)) != KErrNone)
   1.900 +		{
   1.901 +		return KErrArgument;
   1.902 +		}
   1.903 +
   1.904 +	if (iNumCompositionBuffers > 1 && iGetBuffer == iDisplayBuffer)
   1.905 +		{
   1.906 +		// Multi-buffer case, and buffer is currently being displayed
   1.907 +
   1.908 +		if (iBuffer[iGetBuffer].iRequest.SetStatus(*iMsg))
   1.909 +			{
   1.910 +			return KRequestPending;
   1.911 +			}
   1.912 +
   1.913 +		// Already set
   1.914 +		return KErrInUse;
   1.915 +		}
   1.916 +
   1.917 +	return KErrNone;
   1.918 +	}
   1.919 +
   1.920 +
   1.921 +/**
   1.922 +Post a user buffer to the display on the next frame tick.
   1.923 +@param aBufferId	The ID of the user buffer to post.
   1.924 +@param aRegion	NULL if the entire buffer has changed, or a user pointer to up
   1.925 +to TDisplayInfo::KMaxRectagles areas that have changed.
   1.926 +@return KErrNone, or a system-wide error code
   1.927 +*/
   1.928 +TInt DDisplayChannel::PostUserBuffer(RDisplayChannel::TBufferId* aBufferId, TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
   1.929 +	{
   1.930 +	RDisplayChannel::TBufferId bufferId;
   1.931 +	bufferId = reinterpret_cast <RDisplayChannel::TBufferId> (aBufferId);
   1.932 +
   1.933 +	if (!IsUserBuffer(bufferId))
   1.934 +		{
   1.935 +		// Not a user buffer.
   1.936 +		return KErrArgument;
   1.937 +		}
   1.938 +
   1.939 +	if (!iBuffer[bufferId].iChunk)
   1.940 +		{
   1.941 +		// User buffer not initialised.
   1.942 +		return KErrArgument;
   1.943 +		}
   1.944 +
   1.945 +	if (iWaitForPost == iPostCount)
   1.946 +		{
   1.947 +		// Complete wait for post (dropped)
   1.948 +		iWaitForPostRequest.Complete(KErrNone);
   1.949 +		}
   1.950 +
   1.951 +	if (IsUserBuffer(iPostedBuffer))
   1.952 +		{
   1.953 +		// Complete the user post request (not displayed)
   1.954 +		iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
   1.955 +		}
   1.956 +
   1.957 +	if (bufferId == iDisplayBuffer)	//pathological case
   1.958 +		{
   1.959 +		// Complete the current display buffer as we are superceding it with the same one
   1.960 +		iBuffer[bufferId].iRequest.Complete(KErrNone);
   1.961 +		}
   1.962 +
   1.963 +	// Only one buffer can be posted at any time, and if it were this user
   1.964 +	// buffer, the request will have just been completed, so this shouldn't fail.
   1.965 +	TBool isSet = iBuffer[bufferId].iRequest.SetStatus(*iMsg);
   1.966 +
   1.967 +	__ASSERT_DEBUG(isSet, Panic(EDisplayPanicInUse));
   1.968 +	(TAny)isSet;
   1.969 +	iPostedBuffer = bufferId;
   1.970 +
   1.971 +	// Get the region
   1.972 +	if (aRegion)
   1.973 +		{
   1.974 +		// Set iPostedRect(Count) from aRegion.
   1.975 +		Panic(EDisplayPanicNotYetImplemented);
   1.976 +		}
   1.977 +
   1.978 +	iPostCount++;
   1.979 +	iNewRotation = iCurrentRotation;
   1.980 +	iNewResolution = iCurrentResolution;
   1.981 +	iNewBufferFormat = iCurrentBufferFormat;
   1.982 +	SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
   1.983 +
   1.984 +	return KRequestPending;
   1.985 +	}
   1.986 +
   1.987 +/**
   1.988 +Asynchronous request notification when the given post count is reached (or
   1.989 +passed).
   1.990 +@param aStatus	The request status to be completed.
   1.991 +@param aPostCount	The count to wait for.
   1.992 +*/
   1.993 +TInt DDisplayChannel::WaitForPost(RDisplayChannel::TPostCount* aPostCount)
   1.994 +	{
   1.995 +	TInt postCount;
   1.996 +
   1.997 +	kumemget(&postCount, aPostCount, sizeof(RDisplayChannel::TPostCount));
   1.998 +
   1.999 +	if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0)
  1.1000 +		{
  1.1001 +		// Set up the request to be completed when the post occurs
  1.1002 +		if (iWaitForPostRequest.SetStatus(*iMsg))
  1.1003 +			{
  1.1004 +			iWaitForPost = postCount;
  1.1005 +			return KRequestPending;
  1.1006 +			}
  1.1007 +
  1.1008 +		// Already waiting for a post
  1.1009 +		return KErrInUse;
  1.1010 +		}
  1.1011 +
  1.1012 +	// Requested post already displayed/dropped
  1.1013 +	return KErrNone;
  1.1014 +	}
  1.1015 +
  1.1016 +/**
  1.1017 +Asynchronous request notification when the display connection state changes.
  1.1018 +This occurs when the display is disconnected, connected with no list, or a list of modes becomes available or is updated.
  1.1019 +*/
  1.1020 +TInt DDisplayChannel::WaitForDisplayConnect()
  1.1021 +	{
  1.1022 +	
  1.1023 +	Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &iDisplayStateSpinner, NULL, iScreenNumber);
  1.1024 +	
  1.1025 +	if (iWaitForDisplayConnect.SetStatus(*iMsg))
  1.1026 +		{
  1.1027 +		return KRequestPending;
  1.1028 +		}
  1.1029 +
  1.1030 +	// Already waiting for a post
  1.1031 +	return KErrInUse;
  1.1032 +	}
  1.1033 +
  1.1034 +
  1.1035 +/**
  1.1036 +Set the rotation of the screen on the next frame. If the buffer contents will
  1.1037 +not be valid, the flag set. The validity of the buffer is down to whether the
  1.1038 +width and height change.
  1.1039 +
  1.1040 +@param aNewRotation	Address in user space of the new rotation setting.
  1.1041 +@param aDisplayConfigChanged	Address in user space of where to put whether the
  1.1042 +orientation specific info to use has changed following the rotation setting.
  1.1043 +@return KErrNone, or KErrArgument if an argument was invalid.
  1.1044 +*/
  1.1045 +TInt DDisplayChannel::SetRotation(RDisplayChannel::TDisplayRotation* aNewRotation,
  1.1046 +		TBool* aDisplayConfigChanged)
  1.1047 +	{
  1.1048 +	RDisplayChannel::TDisplayRotation newRotation;
  1.1049 +
  1.1050 +	__ASSERT_DEBUG(aNewRotation, Panic(EDisplayPanicNullArgument));
  1.1051 +
  1.1052 +	kumemget(&newRotation, aNewRotation, sizeof(newRotation));
  1.1053 +
  1.1054 +	if (((TInt)newRotation - 1) & newRotation)
  1.1055 +		{
  1.1056 +		// More than one bit is set, which is not valid
  1.1057 +		return KErrArgument;
  1.1058 +		}
  1.1059 +
  1.1060 +	if ((iChannelInfo.iAvailableRotations & newRotation) == 0)
  1.1061 +		{
  1.1062 +		// Rotation is not supported
  1.1063 +		return KErrArgument;
  1.1064 +		}
  1.1065 +
  1.1066 +	TBool displayConfigChanged = (IsFlipped(newRotation) != IsFlipped(iCurrentRotation));
  1.1067 +	iCurrentRotation = newRotation;
  1.1068 +
  1.1069 +	SafePut(aDisplayConfigChanged, &displayConfigChanged, sizeof(TBool));
  1.1070 +
  1.1071 +	return KErrNone;
  1.1072 +	}
  1.1073 +
  1.1074 +
  1.1075 +/**
  1.1076 +Register a user buffer. Assign an ID for it (if available) and open the chunk to
  1.1077 +get the address.
  1.1078 +@param aChunkHandle	The chunk handle.
  1.1079 +@param aOffset		The offset from the chunk base address to the start of the
  1.1080 +buffer.
  1.1081 +@param aBufferId	The address in user space of where to put the buffer ID.
  1.1082 +*/
  1.1083 +TInt DDisplayChannel::RegisterUserBuffer(TInt aChunkHandle, TInt aOffset,
  1.1084 +		RDisplayChannel::TBufferId* aBufferId)
  1.1085 +	{
  1.1086 +	if (!aBufferId)
  1.1087 +		{
  1.1088 +		return KErrArgument;
  1.1089 +		}
  1.1090 +
  1.1091 +	NKern::ThreadEnterCS();
  1.1092 +	DChunk* chunk = Kern::OpenSharedChunk(iMsg->Client(), aChunkHandle,
  1.1093 +			EFalse);
  1.1094 +	NKern::ThreadLeaveCS();
  1.1095 +	if (!chunk)
  1.1096 +		{
  1.1097 +		return KErrBadHandle;
  1.1098 +		}
  1.1099 +
  1.1100 +	TLinAddr kernelAddress;
  1.1101 +
  1.1102 +	const TInt bufferSize = (iDisplayResolution.iWidth * iDisplayResolution.iHeight);
  1.1103 +	TInt r = Kern::ChunkAddress(chunk,aOffset,bufferSize,kernelAddress);
  1.1104 +	if(r!=KErrNone)
  1.1105 +		{
  1.1106 +		NKern::ThreadEnterCS();
  1.1107 +		Kern::ChunkClose(chunk);
  1.1108 +		NKern::ThreadLeaveCS();
  1.1109 +		return r;
  1.1110 +		}
  1.1111 +
  1.1112 +	// Search for an empty slot
  1.1113 +	for (TInt index = KFirstUserBuffer; index < (KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers); index++)
  1.1114 +		{
  1.1115 +		if (!iBuffer[index].iChunk)
  1.1116 +			{
  1.1117 +			// Found one, so fill in the details and return the index as the ID.
  1.1118 +			iBuffer[index].iChunk = chunk;
  1.1119 +			iBuffer[index].iAddress = (TAny*)(kernelAddress);
  1.1120 +			kumemput(aBufferId, &index, sizeof(RDisplayChannel::TBufferId));
  1.1121 +			return KErrNone;
  1.1122 +			}
  1.1123 +		}
  1.1124 +
  1.1125 +	// No slots available.
  1.1126 +	NKern::ThreadEnterCS();
  1.1127 +	Kern::ChunkClose(chunk);
  1.1128 +	NKern::ThreadLeaveCS();
  1.1129 +	return KErrTooBig;
  1.1130 +	}
  1.1131 +
  1.1132 +
  1.1133 +/**
  1.1134 +Deregister a user buffer.
  1.1135 +@param aBufferId	The buffer ID.
  1.1136 +*/
  1.1137 +TInt DDisplayChannel::DeregisterUserBuffer(RDisplayChannel::TBufferId* aBufferId)
  1.1138 +	{
  1.1139 +	RDisplayChannel::TBufferId bufferId;
  1.1140 +	
  1.1141 +	__ASSERT_DEBUG(aBufferId, Panic(EDisplayPanicNullArgument));
  1.1142 +	kumemget(&bufferId, aBufferId, sizeof(RDisplayChannel::TBufferId));
  1.1143 +
  1.1144 +	if (!IsUserBuffer(bufferId))
  1.1145 +		{
  1.1146 +		// Not a valid ID
  1.1147 +		return KErrArgument;
  1.1148 +		}
  1.1149 +
  1.1150 +	TBufferInfo* buffer = &iBuffer[bufferId];
  1.1151 +	if (!buffer->iChunk)
  1.1152 +		{
  1.1153 +		// Not registered
  1.1154 +		return KErrArgument;
  1.1155 +		}
  1.1156 +
  1.1157 +	if (iDisplayBuffer == bufferId)
  1.1158 +		{
  1.1159 +		return KErrInUse;
  1.1160 +		}
  1.1161 +
  1.1162 +	if (iPostedBuffer == bufferId)
  1.1163 +		{
  1.1164 +		// Was queued to be posted
  1.1165 +		iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet;
  1.1166 +		iPostedRectCount = 0;
  1.1167 +		}
  1.1168 +
  1.1169 +	// Cancel any outstanding request on the buffer and clear out the fields.
  1.1170 +	buffer->iRequest.Complete(KErrCancel);
  1.1171 +	NKern::ThreadEnterCS();
  1.1172 +	Kern::ChunkClose(buffer->iChunk);
  1.1173 +	NKern::ThreadLeaveCS();
  1.1174 +	buffer->iChunk = NULL;
  1.1175 +	buffer->iAddress = NULL;
  1.1176 +
  1.1177 +	return KErrNone;
  1.1178 +	}
  1.1179 +
  1.1180 +/**
  1.1181 +Get all resolutions available for this screen and insert to a descriptor
  1.1182 +@return KErrNone if successful, otherwise a system wide error code.
  1.1183 +*/
  1.1184 +TInt DDisplayChannel::GetResolutions()
  1.1185 +	{
  1.1186 +	TInt r;
  1.1187 +	__ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
  1.1188 +	__ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
  1.1189 +	//get the number of resolutions (as above)
  1.1190 +	TInt numberOfResolutions = 0;
  1.1191 +	TInt refStateSpinner, curStateSpinner;
  1.1192 +	//Get the number of resolutions as well as the display state spinner at this point
  1.1193 +	r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &refStateSpinner, iScreenNumber);
  1.1194 +	if(r < KErrNone)
  1.1195 +		{
  1.1196 +		return r;
  1.1197 +		}
  1.1198 +		    	
  1.1199 +	TInt length;
  1.1200 +	TInt maxLength;
  1.1201 +	Kern::KUDesInfo(*(const TDesC*)iMsg->Ptr0(),length,maxLength);
  1.1202 +		    	
  1.1203 +	if ((maxLength/static_cast<TInt>(sizeof(RDisplayChannel::TResolution))) < numberOfResolutions)
  1.1204 +		{
  1.1205 +		return KErrOverflow;
  1.1206 +		}
  1.1207 +		    	
  1.1208 +	TVideoInfoV01 info;
  1.1209 +	TPckg<TVideoInfoV01> infoPckg(info);
  1.1210 +	RDisplayChannel::TResolution resolution = {{0,0},{0,0},RDisplayChannel::ERotationAll};
  1.1211 +	TPtr8 tempDes(NULL,0);
  1.1212 +
  1.1213 +	TInt i;
  1.1214 +	for (i=0;i<numberOfResolutions;i++)
  1.1215 +		{
  1.1216 +		//before filling the package, the display state needs to be checked for consistency
  1.1217 +		Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &curStateSpinner, NULL, iScreenNumber);
  1.1218 +		    			    		
  1.1219 +		if(curStateSpinner != refStateSpinner)
  1.1220 +			{ //display state has changed, the resolution list we trying to get becomes corrupted
  1.1221 +			Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
  1.1222 +			return KErrCorrupt;
  1.1223 +			}
  1.1224 +
  1.1225 +		//pass info package to be filled in, also sending the config to read, and the screen within that
  1.1226 +		Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber);
  1.1227 +		//save resolution
  1.1228 +		resolution.iPixelSize = info.iSizeInPixels;
  1.1229 +		resolution.iTwipsSize = info.iSizeInTwips;
  1.1230 +		//copy resolution
  1.1231 +  		tempDes.Set((TUint8*)&resolution,sizeof(RDisplayChannel::TResolution),sizeof(RDisplayChannel::TResolution));
  1.1232 +   		r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(),tempDes,i*sizeof(RDisplayChannel::TResolution),iMsg->Client());
  1.1233 +		    		
  1.1234 +   		if (r<KErrNone)
  1.1235 +   			{
  1.1236 +   			Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
  1.1237 +   			return r;
  1.1238 +   			}
  1.1239 +   		}
  1.1240 +	Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
  1.1241 +   	SafePut(iMsg->Ptr1(), &numberOfResolutions, sizeof(numberOfResolutions));
  1.1242 +   	return KErrNone;
  1.1243 +	}
  1.1244 +
  1.1245 +
  1.1246 +
  1.1247 +TInt DDisplayChannel::SetResolution(TSize* aSize)
  1.1248 +	{
  1.1249 +	if (!aSize)
  1.1250 +		{
  1.1251 +		ClientPanic(RDisplayChannel::ENullArgument);
  1.1252 +		return KErrArgument;
  1.1253 +		}
  1.1254 +
  1.1255 +	TSize size;
  1.1256 +	kumemget32(&size, aSize, sizeof(size));
  1.1257 +	if (size.iWidth < 0 || size.iHeight < 0)
  1.1258 +		{
  1.1259 +		ClientPanic(RDisplayChannel::EInvalidResolution);
  1.1260 +		return KErrArgument;
  1.1261 +		}
  1.1262 +	
  1.1263 +	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
  1.1264 +			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
  1.1265 +		{
  1.1266 +		return KErrPermissionDenied;
  1.1267 +		}
  1.1268 +
  1.1269 +	// Validate size. Return KErrArgument on failure.
  1.1270 +	//Get the number of resolutions
  1.1271 +	TInt numberOfResolutions;
  1.1272 +	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber);
  1.1273 +	if(r < KErrNone)
  1.1274 +		{
  1.1275 +		return r;
  1.1276 +		}
  1.1277 +	TVideoInfoV01 info;
  1.1278 +	TPckg<TVideoInfoV01> infoPckg(info);
  1.1279 +	for (TInt i = 0; i < numberOfResolutions; i++)
  1.1280 +		{
  1.1281 +		//pass info package to be filled in, also sending the config to read, and the screen within that
  1.1282 +		Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber);
  1.1283 +		
  1.1284 +		if (info.iSizeInPixels.iWidth == size.iWidth &&
  1.1285 +				info.iSizeInPixels.iHeight == size.iHeight)
  1.1286 +			{	//matched resolution
  1.1287 +			iCurrentResolution = size;
  1.1288 +			iCurrentTwips = info.iSizeInTwips;
  1.1289 +			
  1.1290 +			if (iCurrentResolution.iHeight > iNewBufferFormat.iSize.iHeight ||
  1.1291 +				iCurrentResolution.iWidth > iNewBufferFormat.iSize.iWidth)
  1.1292 +				{
  1.1293 +				// going back to initial settings and, we hope, 
  1.1294 +				// the buffers could still be displayed correctly, but we have no guarantee
  1.1295 +				iCurrentBufferFormat = iInitialBufferFormat;
  1.1296 +				}
  1.1297 +			return KErrNone;
  1.1298 +			}
  1.1299 +   		}
  1.1300 +	return KErrArgument;	//if reached here, it did not match aSize to any config resolution
  1.1301 +	}
  1.1302 +
  1.1303 +TInt DDisplayChannel::GetResolution(TSize* aSize)
  1.1304 +	{
  1.1305 +	TInt numberOfResolutions;
  1.1306 +	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions,
  1.1307 +			&numberOfResolutions, NULL, iScreenNumber);
  1.1308 +
  1.1309 +	if (r == KErrNone)
  1.1310 +		{
  1.1311 +		if (numberOfResolutions > 0)
  1.1312 +			{
  1.1313 +		   	SafePut(aSize, &iCurrentResolution, sizeof(iCurrentResolution));
  1.1314 +			}
  1.1315 +		else
  1.1316 +			{
  1.1317 +			TSize resolution = {0,0};
  1.1318 +		   	SafePut(aSize, &resolution, sizeof(resolution));
  1.1319 +			}
  1.1320 +		}
  1.1321 +	return r;
  1.1322 +	}
  1.1323 +
  1.1324 +TInt DDisplayChannel::GetTwips(TSize* aSize)
  1.1325 +	{
  1.1326 +	TInt numberOfResolutions;
  1.1327 +	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions,
  1.1328 +			&numberOfResolutions, NULL, iScreenNumber);
  1.1329 +
  1.1330 +	if (r == KErrNone)
  1.1331 +		{
  1.1332 +		if (numberOfResolutions > 0)
  1.1333 +			{
  1.1334 +		   	SafePut(aSize, &iCurrentTwips, sizeof(iCurrentTwips));
  1.1335 +			}
  1.1336 +		else
  1.1337 +			{
  1.1338 +			TSize twips = {0,0};
  1.1339 +		   	SafePut(aSize, &twips, sizeof(twips));
  1.1340 +			}
  1.1341 +		}
  1.1342 +	return r;
  1.1343 +	}
  1.1344 +/**
  1.1345 +Get all the pixel formats available and insert them to a descriptor
  1.1346 +@return KErrNone if successful, otherwise a system wide error code.
  1.1347 +*/
  1.1348 +TInt DDisplayChannel::GetPixelFormats()
  1.1349 +	{
  1.1350 +	TInt r;
  1.1351 +	__ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
  1.1352 +	__ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
  1.1353 +	//get the number of resolutions (as above)
  1.1354 +	TPtr8 pixelFormatDes(NULL,0);
  1.1355 +	TInt length = ((TInt)sizeof(RDisplayChannel::TPixelFormat)) * iPixelFormatArraySize;
  1.1356 +	pixelFormatDes.Set((TUint8*)iPixelFormatArray, length, length);
  1.1357 +	r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(), pixelFormatDes, 0, iMsg->Client());
  1.1358 +	if (r == KErrNone)
  1.1359 +		{
  1.1360 +		Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(), length);
  1.1361 +		SafePut(iMsg->Ptr1(), &iPixelFormatArraySize, sizeof(iPixelFormatArraySize));
  1.1362 +		}
  1.1363 +	return r;
  1.1364 +	}
  1.1365 +
  1.1366 +
  1.1367 +TInt DDisplayChannel::SetBufferFormat(RDisplayChannel::TBufferFormat* aBufferFormat)
  1.1368 +	{
  1.1369 +	if (!aBufferFormat)
  1.1370 +		{
  1.1371 +		ClientPanic(RDisplayChannel::ENullArgument);
  1.1372 +		return KErrArgument;
  1.1373 +		}
  1.1374 +
  1.1375 +	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
  1.1376 +			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
  1.1377 +		{
  1.1378 +		return KErrPermissionDenied;
  1.1379 +		}
  1.1380 +
  1.1381 +	RDisplayChannel::TBufferFormat bufferFormat;
  1.1382 +	kumemget32(&bufferFormat, aBufferFormat, sizeof(RDisplayChannel::TBufferFormat));
  1.1383 +	
  1.1384 +	// Validate Size
  1.1385 +	if (iCurrentResolution.iHeight > bufferFormat.iSize.iHeight ||
  1.1386 +		iCurrentResolution.iWidth > bufferFormat.iSize.iWidth ||
  1.1387 +		bufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth ||
  1.1388 +		bufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth)
  1.1389 +		{
  1.1390 +		//return error on failure
  1.1391 +		return KErrArgument;
  1.1392 +		}
  1.1393 +	
  1.1394 +	// check we received one of the supported formats.
  1.1395 +	for (TInt i = 0; i < iPixelFormatArraySize; i++)
  1.1396 +		{
  1.1397 +		if (bufferFormat.iPixelFormat == iPixelFormatArray[i])
  1.1398 +			{
  1.1399 +			// the arguments are all validated at this point, update the current format
  1.1400 +			iCurrentBufferFormat = bufferFormat;
  1.1401 +			return KErrNone;
  1.1402 +			}
  1.1403 +		}
  1.1404 +	
  1.1405 +		//return error on failure
  1.1406 +		return KErrArgument;
  1.1407 +	}
  1.1408 +
  1.1409 +TInt DDisplayChannel::ValidateBufferFormat(const RDisplayChannel::TBufferFormat& aBufferFormat,
  1.1410 +									 	   const RDisplayChannel::TResolution& aResolution)
  1.1411 +	{
  1.1412 +	// Validate the size reported in buffer format against the given resolution
  1.1413 +	if (aResolution.iPixelSize.iHeight > aBufferFormat.iSize.iHeight ||
  1.1414 +		aResolution.iPixelSize.iWidth > aBufferFormat.iSize.iWidth ||
  1.1415 +		aBufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth ||
  1.1416 +		aBufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth)
  1.1417 +		{
  1.1418 +		//return error on failure
  1.1419 +		return KErrArgument;
  1.1420 +		}
  1.1421 +	
  1.1422 +	// check we received one of the supported formats.
  1.1423 +	for (TInt i = 0; i < iPixelFormatArraySize; i++)
  1.1424 +		{
  1.1425 +		if (aBufferFormat.iPixelFormat == iPixelFormatArray[i])
  1.1426 +			{
  1.1427 +			return KErrNone;
  1.1428 +			}
  1.1429 +		}
  1.1430 +		
  1.1431 +	return KErrArgument;
  1.1432 +	}
  1.1433 +
  1.1434 +TInt DDisplayChannel::NextPlaneOffset(RDisplayChannel::TBufferFormat* aBufferFormat, 
  1.1435 +		            				 RDisplayChannel::TBufferFormatContext* aContext)
  1.1436 +	{
  1.1437 +	if (!aBufferFormat)
  1.1438 +		{
  1.1439 +		ClientPanic(RDisplayChannel::ENullArgument);
  1.1440 +		return KErrArgument;
  1.1441 +		}
  1.1442 +
  1.1443 +	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
  1.1444 +			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
  1.1445 +		{
  1.1446 +		return KErrPermissionDenied;
  1.1447 +		}
  1.1448 +
  1.1449 +	RDisplayChannel::TBufferFormat bufferFormat;
  1.1450 +	kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat));
  1.1451 +	
  1.1452 +	RDisplayChannel::TResolution resolution;
  1.1453 +	RDisplayChannel::TDisplayRotation rotation;
  1.1454 +	
  1.1455 +	if (aContext)
  1.1456 +		{
  1.1457 +		RDisplayChannel::TBufferFormatContext context;
  1.1458 +		kumemget32(&context, aContext, sizeof(context));
  1.1459 +		resolution = context.iResolution;
  1.1460 +		rotation = context.iRotation;
  1.1461 +		}
  1.1462 +	else
  1.1463 +		{
  1.1464 +		resolution.iPixelSize = iCurrentResolution;
  1.1465 +		rotation = iCurrentRotation;
  1.1466 +		}
  1.1467 +	
  1.1468 +		TInt err = ValidateBufferFormat(bufferFormat, resolution);
  1.1469 +		
  1.1470 +		if (err != KErrNone)
  1.1471 +			{
  1.1472 +			return err;
  1.1473 +			}
  1.1474 +		//it assumes no planar pixel formats are supported by this driver implementation
  1.1475 +		return 0;
  1.1476 +	}
  1.1477 +
  1.1478 +TInt DDisplayChannel::NextLineOffset(RDisplayChannel::TBufferFormat* aBufferFormat, 
  1.1479 +		            				 RDisplayChannel::TBufferFormatContext* aContext)
  1.1480 +	{
  1.1481 +	if (!aBufferFormat)
  1.1482 +		{
  1.1483 +		ClientPanic(RDisplayChannel::ENullArgument);
  1.1484 +		return KErrArgument;
  1.1485 +		}
  1.1486 +
  1.1487 +	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
  1.1488 +			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
  1.1489 +		{
  1.1490 +		return KErrPermissionDenied;
  1.1491 +		}
  1.1492 +
  1.1493 +	RDisplayChannel::TBufferFormat bufferFormat;
  1.1494 +	kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat));
  1.1495 +	
  1.1496 +	RDisplayChannel::TResolution resolution;
  1.1497 +	RDisplayChannel::TDisplayRotation rotation;
  1.1498 +	
  1.1499 +	if (aContext)
  1.1500 +		{
  1.1501 +		RDisplayChannel::TBufferFormatContext context;
  1.1502 +		kumemget32(&context, aContext, sizeof(context));
  1.1503 +		resolution = context.iResolution;
  1.1504 +		rotation = context.iRotation;
  1.1505 +		}
  1.1506 +	else
  1.1507 +		{
  1.1508 +		resolution.iPixelSize = iCurrentResolution;
  1.1509 +		rotation = iCurrentRotation;
  1.1510 +		}
  1.1511 +
  1.1512 +	TInt err = ValidateBufferFormat(bufferFormat, resolution);
  1.1513 +	
  1.1514 +	if (err != KErrNone)
  1.1515 +		{
  1.1516 +		return err;
  1.1517 +		}
  1.1518 +	
  1.1519 +	TInt bpp = 0;
  1.1520 +	//validating the pixel format and getting the pixel size in bits
  1.1521 +	switch (bufferFormat.iPixelFormat)
  1.1522 +		{
  1.1523 +		case EUidPixelFormatXRGB_4444:	// RGB4444
  1.1524 +		case EUidPixelFormatARGB_4444:
  1.1525 +		case EUidPixelFormatRGB_565:	// RGB565
  1.1526 +			bpp = 16;
  1.1527 +			break;
  1.1528 +		case EUidPixelFormatXRGB_8888:	// Really 32bpp, but top 8 unused
  1.1529 +		case EUidPixelFormatARGB_8888:
  1.1530 +		case EUidPixelFormatARGB_8888_PRE:
  1.1531 +			bpp = 32;
  1.1532 +			break;
  1.1533 +		default:
  1.1534 +			// We got an error, it seems. The pixel format is not supported 
  1.1535 +			// Let's panic because the pixel format has just been validated
  1.1536 +			Panic(EDisplayPanicInvalidBitDepth);
  1.1537 +			break;
  1.1538 +		}
  1.1539 +		
  1.1540 +	TInt widthInPixel = 0;	// pixels
  1.1541 +		
  1.1542 +	// let's take in consideration the given rotation
  1.1543 +	switch (rotation)
  1.1544 +		{
  1.1545 +		case RDisplayChannel::ERotation90CW:
  1.1546 +		case RDisplayChannel::ERotation270CW:
  1.1547 +			widthInPixel = bufferFormat.iSize.iHeight;
  1.1548 +			break;
  1.1549 +		default:	// Normal
  1.1550 +			widthInPixel = bufferFormat.iSize.iWidth;
  1.1551 +			break;
  1.1552 +		}
  1.1553 +	
  1.1554 +	// we have to round up to 32 bits word. This is a Ms Windows limitation 
  1.1555 +	TInt stride = _ALIGN_UP((widthInPixel * bpp), 32) >> 3;
  1.1556 +	return stride;
  1.1557 +	}