os/boardsupport/emulator/emulatorbsp/specific/display_chan.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
sl@0
    17
#include <kernel/kern_priv.h>
sl@0
    18
#include <kernel/kernel.h>
sl@0
    19
#include <winsdef.h>
sl@0
    20
#include <emulator.h>
sl@0
    21
#include <pixelformats.h>
sl@0
    22
#include "gui.h"
sl@0
    23
#include "display_chan.h"
sl@0
    24
sl@0
    25
#define WIN32_LEAN_AND_MEAN
sl@0
    26
#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
sl@0
    27
#include <windows.h>
sl@0
    28
#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
sl@0
    29
sl@0
    30
#ifndef DD_TRACE
sl@0
    31
#ifdef DD_TRACE_ENABLED
sl@0
    32
#define DD_TRACE(X) X
sl@0
    33
#else
sl@0
    34
#define DD_TRACE(X)
sl@0
    35
#endif
sl@0
    36
#endif
sl@0
    37
sl@0
    38
sl@0
    39
sl@0
    40
DDisplayChannel::DDisplayChannel() :
sl@0
    41
		iVSync(&DDisplayChannel::VSyncTimerFn, this),
sl@0
    42
		iVSyncDfc(&DDisplayChannel::VSyncDfcFn, this, Kern::DfcQue0(), KDfcPriority),
sl@0
    43
		iPostedBuffer((TUint)KBufferNotSet),
sl@0
    44
		iGetBuffer((TUint)KFirstCompositionBuffer),
sl@0
    45
		iDisplayStateSpinner(0),
sl@0
    46
		iVersion(KDisplayChMajorVersionNumber, 
sl@0
    47
			     KDisplayChMinorVersionNumber, 
sl@0
    48
			     KDisplayChBuildVersionNumber)
sl@0
    49
	{
sl@0
    50
	DD_TRACE(Kern::Printf("DDisplayChannel Creation");)
sl@0
    51
	}
sl@0
    52
sl@0
    53
sl@0
    54
DDisplayChannel::~DDisplayChannel()
sl@0
    55
	{
sl@0
    56
	DD_TRACE(Kern::Printf("DDisplayChannel Destruction");)
sl@0
    57
	//clean up.
sl@0
    58
sl@0
    59
	NKern::ThreadEnterCS();
sl@0
    60
	Kern::Free(iBuffer);
sl@0
    61
	NKern::ThreadLeaveCS();
sl@0
    62
sl@0
    63
	}
sl@0
    64
sl@0
    65
sl@0
    66
/**
sl@0
    67
  Second stage constructor called by the kernel's device driver framework.
sl@0
    68
  This is called in the context of the user thread (client) which requested the creation of a Logical Channel
sl@0
    69
  (E.g. through a call to RBusLogicalChannel::DoCreate)
sl@0
    70
  The thread is in a critical section.
sl@0
    71
sl@0
    72
  @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
sl@0
    73
  @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
sl@0
    74
  @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
sl@0
    75
sl@0
    76
  @return KErrNone if successful, otherwise one of the other system wide error codes.
sl@0
    77
*/
sl@0
    78
TInt DDisplayChannel::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
sl@0
    79
	{
sl@0
    80
	// Check version
sl@0
    81
	if (!Kern::QueryVersionSupported(iDevice->iVersion, aVer))
sl@0
    82
		{
sl@0
    83
		return KErrNotSupported;
sl@0
    84
		}
sl@0
    85
sl@0
    86
	iScreenNumber = aUnit;	/*aUnit?*/
sl@0
    87
	SetDfcQ(Kern::DfcQue0());
sl@0
    88
	iMsgQ.Receive();
sl@0
    89
sl@0
    90
	// Ask the GUI code to initialize the rest of the object.
sl@0
    91
	return Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel,
sl@0
    92
			(TAny*)iScreenNumber, this);
sl@0
    93
	}
sl@0
    94
sl@0
    95
sl@0
    96
void DDisplayChannel::ValidateSpecificInfo(TInt aBytesPerPixel, RDisplayChannel::TOrientationSpecificInfo& aInfo)
sl@0
    97
	{
sl@0
    98
	__ASSERT_DEBUG(aInfo.iWidth > 0 && aInfo.iHeight > 0, Panic(EDisplayPanicInvalidDimensions));
sl@0
    99
	__ASSERT_DEBUG(aInfo.iOffsetBetweenLines > 0, Panic(EDisplayPanicInvalidStride));
sl@0
   100
	__ASSERT_DEBUG(aInfo.iWidth * aBytesPerPixel <= (TUint)aInfo.iOffsetBetweenLines, Panic(EDisplayPanicInvalidStride));
sl@0
   101
	
sl@0
   102
	//this is just to stop compiler complaining..
sl@0
   103
	(TAny)aBytesPerPixel;
sl@0
   104
	(TAny)aInfo;
sl@0
   105
	}
sl@0
   106
sl@0
   107
/**
sl@0
   108
Finish creating the display channel object.
sl@0
   109
sl@0
   110
@param aInfo			Display description object
sl@0
   111
@param aRotation		Initial rotation
sl@0
   112
@param aHwnd			Associated window handle
sl@0
   113
@param aFrameBuffers	Array of one or more pointers to frame buffers
sl@0
   114
@param aResolution		Initial resolution
sl@0
   115
@param aTwips           Size in twips
sl@0
   116
@return	KErrNone if successful, or a system-wide error otherwise.
sl@0
   117
*/
sl@0
   118
TInt DDisplayChannel::Initialize(RDisplayChannel::TDisplayInfo& aInfo, 
sl@0
   119
		                         RDisplayChannel::TDisplayRotation aRotation,
sl@0
   120
		                         HWND aHwnd, RPointerArray<TAny>& aFrameBuffers, 
sl@0
   121
		                         RPointerArray<TBufferAddressA>& aChunks,
sl@0
   122
								 TScreenBuffer& aDsaBuffer,
sl@0
   123
		                         TSize aResolution, 
sl@0
   124
		                         TSize aTwips,
sl@0
   125
		                         const RDisplayChannel::TPixelFormat aPixelFormatArray[],
sl@0
   126
								 const TInt aPixelFormatArraySize,
sl@0
   127
								 const RDisplayChannel::TBufferFormat& aBufferFormat)
sl@0
   128
sl@0
   129
	{
sl@0
   130
	__ASSERT_DEBUG(aInfo.iBitsPerPixel >= 12 && aInfo.iBitsPerPixel <= 32, Panic(EDisplayPanicInvalidBitDepth));
sl@0
   131
	__ASSERT_DEBUG(aInfo.iRefreshRateHz > 0, Panic(EDisplayPanicInvalidRefreshRate));
sl@0
   132
	__ASSERT_DEBUG(aInfo.iAvailableRotations & aRotation, Panic(EDisplayPanicInvalidRotation));
sl@0
   133
	__ASSERT_DEBUG(aInfo.iNormal.iWidth == aInfo.iFlipped.iHeight, Panic(EDisplayPanicInvalidDimensions));
sl@0
   134
	__ASSERT_DEBUG(aInfo.iNormal.iHeight == aInfo.iFlipped.iWidth, Panic(EDisplayPanicInvalidDimensions));
sl@0
   135
	__ASSERT_DEBUG(aRotation == RDisplayChannel::ERotationNormal ||
sl@0
   136
					aRotation == RDisplayChannel::ERotation90CW ||
sl@0
   137
					aRotation == RDisplayChannel::ERotation180 ||
sl@0
   138
					aRotation == RDisplayChannel::ERotation270CW, Panic(EDisplayPanicInvalidRotation));
sl@0
   139
	__ASSERT_DEBUG(aFrameBuffers.Count() > 0, Panic(EDisplayPanicInvalidFrameBuffers));
sl@0
   140
	__ASSERT_DEBUG(aHwnd, Panic(EDisplayPanicInvalidWindowHandle));
sl@0
   141
sl@0
   142
	ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iNormal);
sl@0
   143
	ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iFlipped);
sl@0
   144
sl@0
   145
	// aFrameBuffers includes the legacy buffer at index 0.
sl@0
   146
	iNumCompositionBuffers = aFrameBuffers.Count() - 1;
sl@0
   147
	iTotalBuffers = KFirstCompositionBuffer + iNumCompositionBuffers;
sl@0
   148
	iBuffer = (TBufferInfo*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferInfo));
sl@0
   149
	iChunks = (TBufferAddressA*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferAddressA));
sl@0
   150
	if (!iBuffer)
sl@0
   151
		{
sl@0
   152
		return KErrNoMemory;
sl@0
   153
		}
sl@0
   154
sl@0
   155
	aInfo.iNumCompositionBuffers = iNumCompositionBuffers;
sl@0
   156
	for (TUint index = 0; index < iNumCompositionBuffers; index++)
sl@0
   157
		{
sl@0
   158
		iBuffer[index + KFirstCompositionBuffer].iAddress = aFrameBuffers[index + 1];
sl@0
   159
		iChunks[index + KFirstCompositionBuffer].iChunk = aChunks[index + 1]->iChunk;
sl@0
   160
		}
sl@0
   161
		
sl@0
   162
	iChannelInfo = aInfo;
sl@0
   163
	
sl@0
   164
	iDisplayRotation = iCurrentRotation = aRotation;
sl@0
   165
	iDisplayResolution = iCurrentResolution = aResolution;
sl@0
   166
	iCurrentTwips = aTwips;
sl@0
   167
	iHwnd = aHwnd;
sl@0
   168
	
sl@0
   169
	// Ensure the VSync DFC is on the same queue as the message handling.
sl@0
   170
	iVSyncTicks = NKern::TimerTicks(1000 / aInfo.iRefreshRateHz);
sl@0
   171
    iVSync.OneShot(iVSyncTicks);
sl@0
   172
sl@0
   173
	if (aDsaBuffer.iMemChunks.Count() != 0)
sl@0
   174
		{	
sl@0
   175
		iBuffer[KLegacyBuffer].iAddress = aDsaBuffer.iFrameBuffers[0];
sl@0
   176
		}
sl@0
   177
	else
sl@0
   178
		{
sl@0
   179
		iBuffer[KLegacyBuffer].iAddress = NULL;
sl@0
   180
		}
sl@0
   181
    
sl@0
   182
	iPixelFormatArray = aPixelFormatArray;
sl@0
   183
	iPixelFormatArraySize = aPixelFormatArraySize;
sl@0
   184
sl@0
   185
	// copy the initial buffer format
sl@0
   186
	iInitialBufferFormat = aBufferFormat;
sl@0
   187
	iDisplayBufferFormat = iInitialBufferFormat;
sl@0
   188
	iCurrentBufferFormat = iDisplayBufferFormat;
sl@0
   189
	return KErrNone;
sl@0
   190
	}
sl@0
   191
sl@0
   192
sl@0
   193
/**
sl@0
   194
Set the address of the legacy buffer. 
sl@0
   195
 
sl@0
   196
@param aAddress			Pointer to the legacy buffer. 
sl@0
   197
*/
sl@0
   198
void DDisplayChannel::SetLegacyBuffer(void *aAddress)
sl@0
   199
	{ 
sl@0
   200
	iBuffer[KLegacyBuffer].iAddress = aAddress;
sl@0
   201
	}
sl@0
   202
sl@0
   203
sl@0
   204
sl@0
   205
/**
sl@0
   206
Handle a message on this display for the logical channel.
sl@0
   207
sl@0
   208
@param aMsg	The message to process. The iValue member of this distinguishes the
sl@0
   209
		message type:
sl@0
   210
		iValue == ECloseMsg, channel close message
sl@0
   211
		iValue == KMaxTInt, a 'DoCancel' message
sl@0
   212
		iValue >= 0, a 'DoControl' message with function number equal to iValue
sl@0
   213
		iValue < 0, a 'DoRequest' message with function number equal to ~iValue
sl@0
   214
*/
sl@0
   215
void DDisplayChannel::HandleMsg(TMessageBase* aMsg)
sl@0
   216
	{
sl@0
   217
	iMsg = (TThreadMessage*)aMsg;
sl@0
   218
	TInt id = iMsg->iValue;
sl@0
   219
	TInt r = KErrNone;
sl@0
   220
sl@0
   221
    if (id == (TInt)ECloseMsg)
sl@0
   222
       {
sl@0
   223
       iVSync.Cancel();
sl@0
   224
	   iWaitForPostRequest.Complete(KErrCancel);
sl@0
   225
	   iWaitForDisplayConnect.Complete(KErrCancel);
sl@0
   226
       if (iBuffer)
sl@0
   227
	       	{
sl@0
   228
    		// Unhook display channel from the GUI code if initialized.
sl@0
   229
    		if (iBuffer[KLegacyBuffer].iAddress)
sl@0
   230
	       		{
sl@0
   231
    		      	Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel,
sl@0
   232
	   					(TAny*)iScreenNumber, NULL);
sl@0
   233
        	   		PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0, 0);
sl@0
   234
		      	    InvalidateRect(iHwnd, NULL, FALSE);
sl@0
   235
    			}
sl@0
   236
sl@0
   237
	       	RDisplayChannel::TBufferId index = iTotalBuffers;
sl@0
   238
sl@0
   239
    		while (index-- > 0)
sl@0
   240
	       		{
sl@0
   241
		          	iBuffer[index].iRequest.Complete(KErrCancel);
sl@0
   242
sl@0
   243
        			if (IsUserBuffer(index))
sl@0
   244
		          		{
sl@0
   245
        				// Close chunk
sl@0
   246
		          		if (iBuffer[index].iChunk)
sl@0
   247
        					{
sl@0
   248
		              			NKern::ThreadEnterCS();
sl@0
   249
            					Kern::ChunkClose(iBuffer[index].iChunk);
sl@0
   250
            					NKern::ThreadLeaveCS();
sl@0
   251
        					}
sl@0
   252
				        }
sl@0
   253
			     }
sl@0
   254
sl@0
   255
            }
sl@0
   256
			iMsg->Complete(KErrNone, EFalse);
sl@0
   257
			return;
sl@0
   258
        }
sl@0
   259
sl@0
   260
	if (id < 0)
sl@0
   261
		{
sl@0
   262
		DoRequest(~id);
sl@0
   263
		r = KErrNone;
sl@0
   264
		}
sl@0
   265
	else
sl@0
   266
		{
sl@0
   267
		r = (id == KMaxTInt) ? DoCancel(iMsg->Int0()) : DoControl(id);
sl@0
   268
		}
sl@0
   269
sl@0
   270
	iMsg->Complete(r, (id != ECloseMsg));
sl@0
   271
	}
sl@0
   272
sl@0
   273
sl@0
   274
/**
sl@0
   275
Process synchronous 'control' requests. Parameters are in the first two
sl@0
   276
arguments of iMsg.
sl@0
   277
*/
sl@0
   278
TInt DDisplayChannel::DoControl(TInt aFunction)
sl@0
   279
	{
sl@0
   280
	DD_TRACE(Kern::Printf(">DDisplayChannel::DoControl fn=%d\n", aFunction);)
sl@0
   281
sl@0
   282
	TInt r = KErrNotSupported;
sl@0
   283
	TPckgBuf<RDisplayChannel::TDisplayInfo> pkg(iChannelInfo);
sl@0
   284
	switch(aFunction)
sl@0
   285
		{
sl@0
   286
		case RDisplayChannel::ECtrlGetDisplayInfo:
sl@0
   287
			// a1: TDisplayInfo* info [out]
sl@0
   288
			Kern::KUDesPut(*(TDes8*)iMsg->Ptr0(), pkg); ///*&iChannelInfo*/);
sl@0
   289
			r = KErrNone;
sl@0
   290
			break;
sl@0
   291
sl@0
   292
		case RDisplayChannel::ECtrlOpen:
sl@0
   293
			// Everything is done in Construct
sl@0
   294
			r = KErrNone;
sl@0
   295
			break;
sl@0
   296
sl@0
   297
		case RDisplayChannel::ECtrlClose:
sl@0
   298
			// Nothing to do?
sl@0
   299
			r = KErrNone;
sl@0
   300
			break;
sl@0
   301
sl@0
   302
		case RDisplayChannel::ECtrlPostCompositionBuffer:
sl@0
   303
			// a1: const TRegionFix<KMaxRectangles>* region [in]
sl@0
   304
			// a2: TPostCount* post count [out]
sl@0
   305
			r = PostCompositionBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1());
sl@0
   306
			break;
sl@0
   307
sl@0
   308
		case RDisplayChannel::ECtrlPostLegacyBuffer:
sl@0
   309
			// a1: const TRegionFix<KMaxRectangles>* region [in]
sl@0
   310
			// a2: TPostCount* post count [out]
sl@0
   311
			r = PostLegacyBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1());
sl@0
   312
			break;
sl@0
   313
sl@0
   314
		case RDisplayChannel::ECtrlRegisterUserBuffer:
sl@0
   315
			// a1: { TInt Chunk handle, TInt offset }* [in]
sl@0
   316
			// a2: TInt* buffer ID [out]
sl@0
   317
			{
sl@0
   318
			__ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
sl@0
   319
			TInt arg[2];
sl@0
   320
			kumemget(arg, iMsg->Ptr0(), sizeof(arg));
sl@0
   321
			r = RegisterUserBuffer(arg[0], arg[1], (RDisplayChannel::TBufferId*)iMsg->Ptr1());
sl@0
   322
			}
sl@0
   323
			break;
sl@0
   324
sl@0
   325
		case RDisplayChannel::ECtrlDeregisterUserBuffer:
sl@0
   326
			// a1: TBufferId* buffer ID [in]
sl@0
   327
			r = DeregisterUserBuffer((RDisplayChannel::TBufferId*)iMsg->Ptr0());
sl@0
   328
			break;
sl@0
   329
sl@0
   330
		case RDisplayChannel::ECtrlSetRotation:
sl@0
   331
			// a1: TDisplayRotation* new rotation [in]
sl@0
   332
			// a2: TBool* display config has changed [out]
sl@0
   333
			r = SetRotation((RDisplayChannel::TDisplayRotation*)iMsg->Ptr0(), (TBool*)iMsg->Ptr1());
sl@0
   334
			break;
sl@0
   335
sl@0
   336
		case RDisplayChannel::ECtrlCurrentRotation:
sl@0
   337
			// a1: TDisplayRotation* current rotation [out]
sl@0
   338
			r = SafePut(iMsg->Ptr0(), &iCurrentRotation, sizeof(iCurrentRotation));
sl@0
   339
			break;
sl@0
   340
sl@0
   341
		case ECloseMsg:
sl@0
   342
			r = KErrNone;
sl@0
   343
			break;
sl@0
   344
sl@0
   345
	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:
sl@0
   346
    	    {
sl@0
   347
    	    TInt arg[2];
sl@0
   348
    	    TInt index = *((TInt*)(iMsg->Ptr0()));
sl@0
   349
            r = Kern::MakeHandleAndOpen(iMsg->Client(), iChunks[index + KFirstCompositionBuffer].iChunk);
sl@0
   350
            if(r >= 0)
sl@0
   351
                {
sl@0
   352
	            arg[0] = r;
sl@0
   353
	            arg[1] = 0;
sl@0
   354
				SafePut(iMsg->Ptr1(),&arg,(sizeof(TInt)*2));
sl@0
   355
                r = KErrNone;
sl@0
   356
                }
sl@0
   357
             }
sl@0
   358
    	    break;
sl@0
   359
    	 // added to v1.0
sl@0
   360
	    case RDisplayChannel::ECtrlVersion:
sl@0
   361
			r = SafePut(iMsg->Ptr0(), &iVersion, sizeof(iVersion));
sl@0
   362
	    	break;
sl@0
   363
    	//v1_1
sl@0
   364
	    case RDisplayChannel::ECtrlNumberOfResolutions:
sl@0
   365
	    	{
sl@0
   366
	    	r = NumberOfResolutions();
sl@0
   367
	    	}
sl@0
   368
	    	break;
sl@0
   369
	    case RDisplayChannel::ECtrlGetResolutions:
sl@0
   370
	    	{
sl@0
   371
	    	r = GetResolutions();
sl@0
   372
	    	if(r == KErrCorrupt) //Resolution list changed during GetResolutions
sl@0
   373
	    		{//second go
sl@0
   374
	    		r = GetResolutions();
sl@0
   375
	    		}
sl@0
   376
	    	}
sl@0
   377
	    	break;
sl@0
   378
	    case RDisplayChannel::ECtrlSetResolution:
sl@0
   379
	    	{
sl@0
   380
	    	r = SetResolution((TSize*)iMsg->Ptr0());
sl@0
   381
	    	}
sl@0
   382
	    	break;
sl@0
   383
	    case RDisplayChannel::ECtrlGetResolution:
sl@0
   384
	    	{
sl@0
   385
	    	r = GetResolution((TSize*)iMsg->Ptr0());
sl@0
   386
	    	}
sl@0
   387
	    	break;
sl@0
   388
	    case RDisplayChannel::ECtrlGetTwips:
sl@0
   389
	    	{
sl@0
   390
	    	r = GetTwips((TSize*)iMsg->Ptr0());
sl@0
   391
	    	}
sl@0
   392
	    	break;
sl@0
   393
	    case RDisplayChannel::ECtrlNumberOfPixelFormats:
sl@0
   394
			r = iPixelFormatArraySize;
sl@0
   395
	    	break;
sl@0
   396
	    case RDisplayChannel::ECtrlGetPixelFormats:
sl@0
   397
	    	r = GetPixelFormats();
sl@0
   398
	    	break;
sl@0
   399
	    case RDisplayChannel::ECtrlSetBufferFormat:
sl@0
   400
	    	r = SetBufferFormat((RDisplayChannel::TBufferFormat*)iMsg->Ptr0());
sl@0
   401
	    	break;
sl@0
   402
	    case RDisplayChannel::ECtrlGetBufferFormat:
sl@0
   403
			r = SafePut(iMsg->Ptr0(), &iCurrentBufferFormat, sizeof(iCurrentBufferFormat));
sl@0
   404
	    	break;
sl@0
   405
	    case RDisplayChannel::ECtrlNextPlaneOffset:
sl@0
   406
	    	// we support, for moment only packed pixel formats
sl@0
   407
	    	r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL);
sl@0
   408
	    	break;
sl@0
   409
	    case RDisplayChannel::ECtrlNextLineOffset:
sl@0
   410
	    	// use the internal current resolution and current rotation
sl@0
   411
	    	r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL);
sl@0
   412
	    	break;
sl@0
   413
	    case RDisplayChannel::ECtrlNextPlaneOffsetExtended:
sl@0
   414
	    	// we support, for moment only packed pixel formats
sl@0
   415
	    	r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(),
sl@0
   416
	    			            (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1());
sl@0
   417
	    	break;
sl@0
   418
	    case RDisplayChannel::ECtrlNextLineOffsetExtended:
sl@0
   419
	    	r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(),
sl@0
   420
	    			           (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1());
sl@0
   421
	    	break;
sl@0
   422
		}
sl@0
   423
	DD_TRACE(Kern::Printf("<DDisplayChannel::DoControl result=%d\n",r);)
sl@0
   424
	return r;
sl@0
   425
	}
sl@0
   426
sl@0
   427
TInt DDisplayChannel::GetIndexForSize(const TSize& aSize,TInt& aSpinnerOut)
sl@0
   428
	{
sl@0
   429
	TInt numberOfResolutions = 0;
sl@0
   430
	TInt spinner1 = 0;
sl@0
   431
	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &spinner1, iScreenNumber);
sl@0
   432
	if(r < KErrNone)
sl@0
   433
		return r;
sl@0
   434
	TVideoInfoV01 info;
sl@0
   435
	TPckg<TVideoInfoV01> infoPckg(info);
sl@0
   436
sl@0
   437
	for (TInt res=0;res<numberOfResolutions;res++)
sl@0
   438
		{
sl@0
   439
		//pass info package to be filled in, also sending the config to read, and the screen within that
sl@0
   440
		Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, (TAny*)&res, (TAny*)&infoPckg, iScreenNumber);
sl@0
   441
		if (info.iSizeInPixels.iWidth==aSize.iWidth && info.iSizeInPixels.iHeight==aSize.iHeight)
sl@0
   442
			{
sl@0
   443
			r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &aSpinnerOut, iScreenNumber);
sl@0
   444
			if(r < KErrNone)
sl@0
   445
				return r;
sl@0
   446
			if (aSpinnerOut!=spinner1)
sl@0
   447
				{
sl@0
   448
				return KErrCorrupt;
sl@0
   449
				}
sl@0
   450
			else
sl@0
   451
				{
sl@0
   452
				return res;
sl@0
   453
				}
sl@0
   454
			}
sl@0
   455
		}
sl@0
   456
	return KErrArgument;
sl@0
   457
	}
sl@0
   458
sl@0
   459
/**
sl@0
   460
Process asynchronous requests. TRequestStatus is at iMsg->Ptr0(), and the other
sl@0
   461
two parameters are in iMsg->Ptr1() and iMsg->Ptr2().
sl@0
   462
*/
sl@0
   463
void DDisplayChannel::DoRequest(TInt aFunction)
sl@0
   464
	{
sl@0
   465
	DD_TRACE(Kern::Printf(">DDisplayChannel::DoRequest fn=%d\n", aFunction);)
sl@0
   466
sl@0
   467
	TInt r = KErrNotSupported;
sl@0
   468
sl@0
   469
	switch(aFunction)
sl@0
   470
		{
sl@0
   471
		case RDisplayChannel::EReqGetCompositionBuffer:
sl@0
   472
			// a1: TAny** buffer address [out]
sl@0
   473
			r = GetCompositionBuffer(static_cast<TAny**>(iMsg->Ptr1()));
sl@0
   474
			break;
sl@0
   475
sl@0
   476
		case RDisplayChannel::EReqPostUserBuffer:
sl@0
   477
			// a1: { TBufferId* buffer ID, const TRegionFix<KMaxRectangles>* region }* [in]
sl@0
   478
			// a2: TPostCount* post count [out]
sl@0
   479
			{
sl@0
   480
			TAny* arg[2];
sl@0
   481
			__ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
sl@0
   482
			kumemget(arg, iMsg->Ptr1(), sizeof(arg));
sl@0
   483
			r = PostUserBuffer(reinterpret_cast<RDisplayChannel::TBufferId*>(arg[0]), arg[1],
sl@0
   484
					reinterpret_cast<RDisplayChannel::TPostCount*>(iMsg->Ptr2()));
sl@0
   485
			}
sl@0
   486
			break;
sl@0
   487
sl@0
   488
		case RDisplayChannel::EReqWaitForPost:
sl@0
   489
			// a1: TInt* post to wait for [in]
sl@0
   490
			r = WaitForPost(static_cast<RDisplayChannel::TPostCount*>(iMsg->Ptr1()));
sl@0
   491
			break;
sl@0
   492
	    	//v1_1
sl@0
   493
		case RDisplayChannel::EReqWaitForDisplayConnect:
sl@0
   494
			r = WaitForDisplayConnect();
sl@0
   495
			break;
sl@0
   496
		}
sl@0
   497
sl@0
   498
	DD_TRACE(Kern::Printf("<DDisplayChannel::DoRequest result=%d\n",r);)
sl@0
   499
sl@0
   500
	if (r != KRequestPending)
sl@0
   501
		{
sl@0
   502
		TRequestStatus* status = reinterpret_cast<TRequestStatus*>(iMsg->Ptr0());
sl@0
   503
		Kern::RequestComplete(iMsg->Client(), status, r);
sl@0
   504
		}
sl@0
   505
	}
sl@0
   506
sl@0
   507
sl@0
   508
/**
sl@0
   509
Process asynchronous request cancellations
sl@0
   510
*/
sl@0
   511
TInt DDisplayChannel::DoCancel(TInt aRequestMask)
sl@0
   512
	{
sl@0
   513
	DD_TRACE(Kern::Printf(">DDisplayChannel::DoCancel mask=%x\n", aRequestMask);)
sl@0
   514
sl@0
   515
	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelGetCompositionBuffer))
sl@0
   516
		{
sl@0
   517
		if (IsCompositionBuffer(iGetBuffer))
sl@0
   518
			{
sl@0
   519
			iBuffer[iGetBuffer].iRequest.Complete(KErrCancel);
sl@0
   520
			}
sl@0
   521
		}
sl@0
   522
sl@0
   523
	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelPostUserBuffer))
sl@0
   524
		{
sl@0
   525
		if (IsUserBuffer(iPostedBuffer))
sl@0
   526
			{
sl@0
   527
			iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
sl@0
   528
			}
sl@0
   529
		}
sl@0
   530
sl@0
   531
	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForPost))
sl@0
   532
		{
sl@0
   533
		iWaitForPostRequest.Complete(KErrCancel);
sl@0
   534
		}
sl@0
   535
	if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForDisplayConnect))
sl@0
   536
		{
sl@0
   537
		iWaitForDisplayConnect.Complete(KErrCancel);
sl@0
   538
		}
sl@0
   539
sl@0
   540
	DD_TRACE(Kern::Printf("<DDisplayChannel::DoCancel\n",r);)
sl@0
   541
	return KErrNone;
sl@0
   542
	}
sl@0
   543
sl@0
   544
sl@0
   545
/**
sl@0
   546
Get the number of resolutions on this screen
sl@0
   547
@return Number of resolutions if successful, otherwise a system wide error code.
sl@0
   548
*/
sl@0
   549
TInt DDisplayChannel::NumberOfResolutions()
sl@0
   550
	{
sl@0
   551
	TInt numberOfResolutions = 0;
sl@0
   552
	TInt error = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber);
sl@0
   553
	if (error != KErrNone)
sl@0
   554
		{
sl@0
   555
		return error;
sl@0
   556
		}
sl@0
   557
	return numberOfResolutions;
sl@0
   558
	}
sl@0
   559
sl@0
   560
sl@0
   561
/**
sl@0
   562
Safely write from kernel to user memory.
sl@0
   563
@param aDst	Pointer to destination, user memory.
sl@0
   564
@param aSrc	Pointer to source, kernel memory.
sl@0
   565
@param aBytes	Number of bytes to write.
sl@0
   566
@return KErrNone if successful, KErrArgument if either pointer is NULL.
sl@0
   567
*/
sl@0
   568
TInt DDisplayChannel::SafePut(TAny* aDst, TAny* aSrc, TInt aBytes)
sl@0
   569
	{
sl@0
   570
	if (!aDst || !aSrc)
sl@0
   571
		{
sl@0
   572
		return KErrArgument;
sl@0
   573
		}
sl@0
   574
sl@0
   575
	kumemput(aDst, aSrc, aBytes);
sl@0
   576
	return KErrNone;
sl@0
   577
	}
sl@0
   578
sl@0
   579
sl@0
   580
/**
sl@0
   581
Driver panic.
sl@0
   582
@param	aPanic	The cause of the panic.
sl@0
   583
*/
sl@0
   584
void DDisplayChannel::Panic(TDisplayPanic aPanic)
sl@0
   585
	{
sl@0
   586
	Kern::Fault("DISPLAY", aPanic);
sl@0
   587
	}
sl@0
   588
sl@0
   589
sl@0
   590
/**
sl@0
   591
Client panic.
sl@0
   592
@param	aPanic	The cause of the panic.
sl@0
   593
*/
sl@0
   594
void DDisplayChannel::ClientPanic(RDisplayChannel::TPanic aPanic)
sl@0
   595
	{
sl@0
   596
	_LIT(KLitDisplayChannel, "DISPLAYCHANNEL");
sl@0
   597
	Kern::ThreadKill(iClient, EExitPanic, aPanic, KLitDisplayChannel);
sl@0
   598
	}
sl@0
   599
sl@0
   600
sl@0
   601
/**
sl@0
   602
VSync is emulated by using a nanokernel timer to call this function at the
sl@0
   603
frame rate.
sl@0
   604
*/
sl@0
   605
void DDisplayChannel::VSyncTimerFn(TAny* aDisplayChannel)
sl@0
   606
	{
sl@0
   607
	reinterpret_cast<DDisplayChannel*>(aDisplayChannel)->DoVSyncTimer();
sl@0
   608
	}
sl@0
   609
sl@0
   610
/**
sl@0
   611
Instance function called on the timer thread. Queues the VSyncDfc to run on its
sl@0
   612
thread.
sl@0
   613
*/
sl@0
   614
void DDisplayChannel::DoVSyncTimer(void)
sl@0
   615
	{
sl@0
   616
	iVSyncDfc.Add();
sl@0
   617
	iVSync.Again(iVSyncTicks);
sl@0
   618
	}
sl@0
   619
sl@0
   620
sl@0
   621
/**
sl@0
   622
DFC function to post the current buffer to the display.
sl@0
   623
@param aDisplayImpl	The display object to be posted.
sl@0
   624
*/
sl@0
   625
void DDisplayChannel::VSyncDfcFn(TAny* aDisplayChannel)
sl@0
   626
	{
sl@0
   627
	reinterpret_cast<DDisplayChannel*>(aDisplayChannel)->DoVSync();
sl@0
   628
	}
sl@0
   629
sl@0
   630
sl@0
   631
/**
sl@0
   632
Post the current buffer to the display. Signal waiting threads under various
sl@0
   633
conditions. This is run off the same DFC queue as message handling, so there is
sl@0
   634
no need to protect the fields.
sl@0
   635
*/
sl@0
   636
void DDisplayChannel::DoVSync(void)
sl@0
   637
	{
sl@0
   638
	if(iWaitForDisplayConnect.iStatus)
sl@0
   639
		{
sl@0
   640
		TInt currentSpinner;
sl@0
   641
		Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &currentSpinner, NULL, iScreenNumber);
sl@0
   642
		//display state changed
sl@0
   643
		if(currentSpinner != iDisplayStateSpinner)
sl@0
   644
			iWaitForDisplayConnect.Complete(KErrNone);
sl@0
   645
		}
sl@0
   646
		
sl@0
   647
	if (IsValidBuffer(iPostedBuffer))
sl@0
   648
		{
sl@0
   649
		// Complete any outstanding request for the buffer which was displayed.
sl@0
   650
		// This either signifies the user or composition buffer becoming
sl@0
   651
		// available 
sl@0
   652
		if (iDisplayBuffer != iPostedBuffer)
sl@0
   653
			{
sl@0
   654
			iBuffer[iDisplayBuffer].iRequest.Complete(KErrNone);
sl@0
   655
			}
sl@0
   656
sl@0
   657
		iDisplayBuffer = (RDisplayChannel::TBufferId)iPostedBuffer;
sl@0
   658
		iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet;
sl@0
   659
sl@0
   660
		// Update the pixel pointer used when painting the client window		
sl@0
   661
		PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0,
sl@0
   662
				(LPARAM)iBuffer[iDisplayBuffer].iAddress);
sl@0
   663
sl@0
   664
		// check if the buffer format is modified
sl@0
   665
	if ((iDisplayBufferFormat.iSize.iHeight != iNewBufferFormat.iSize.iHeight) || 
sl@0
   666
		(iDisplayBufferFormat.iSize.iWidth != iNewBufferFormat.iSize.iWidth) ||
sl@0
   667
		(iDisplayBufferFormat.iPixelFormat != iNewBufferFormat.iPixelFormat))
sl@0
   668
		{
sl@0
   669
		// We post in one messages everything, but we got to pack the size
sl@0
   670
		// speculate that the maximum width and height can be represented in 16 bit
sl@0
   671
		TUint aggregateSize = ((TUint)iNewBufferFormat.iSize.iHeight << 16) & 0xffff0000; 
sl@0
   672
		aggregateSize += (TUint)iNewBufferFormat.iSize.iWidth & 0x0000ffff;
sl@0
   673
		PostMessage(iHwnd, 
sl@0
   674
				    WMU_SET_BUFFER_FORMAT, 
sl@0
   675
				    aggregateSize, 
sl@0
   676
				    iNewBufferFormat.iPixelFormat);
sl@0
   677
		iDisplayBufferFormat = iNewBufferFormat;
sl@0
   678
		}
sl@0
   679
	
sl@0
   680
		if (iDisplayRotation != iNewRotation)
sl@0
   681
			{
sl@0
   682
			iDisplayRotation = iNewRotation;
sl@0
   683
sl@0
   684
			TUint flip;
sl@0
   685
			switch (iDisplayRotation)
sl@0
   686
				{
sl@0
   687
				case RDisplayChannel::ERotation90CW:
sl@0
   688
					flip = EEmulatorFlipLeft;
sl@0
   689
					break;
sl@0
   690
				case RDisplayChannel::ERotation180:
sl@0
   691
					flip = EEmulatorFlipInvert;
sl@0
   692
					break;
sl@0
   693
				case RDisplayChannel::ERotation270CW:
sl@0
   694
					flip = EEmulatorFlipRight;
sl@0
   695
					break;
sl@0
   696
				default:	// Normal
sl@0
   697
					flip = EEmulatorFlipRestore;
sl@0
   698
					break;
sl@0
   699
				}
sl@0
   700
			PostMessage(iHwnd, WM_FLIP_MESSAGE, flip, NULL);
sl@0
   701
sl@0
   702
			iPostedRectCount = 0;	// Force full invalidation
sl@0
   703
			}
sl@0
   704
sl@0
   705
		if (iDisplayResolution.iWidth != iNewResolution.iWidth ||
sl@0
   706
				iDisplayResolution.iHeight != iNewResolution.iHeight)
sl@0
   707
			{
sl@0
   708
			iDisplayResolution = iNewResolution;
sl@0
   709
			PostMessage(iHwnd, WMU_SET_DISPLAY_SIZE, 
sl@0
   710
					iDisplayResolution.iWidth, iDisplayResolution.iHeight);
sl@0
   711
			}
sl@0
   712
	
sl@0
   713
		
sl@0
   714
		// Invalidate the window contents where necessary
sl@0
   715
		TInt count = iPostedRectCount;
sl@0
   716
		if (count)
sl@0
   717
			{
sl@0
   718
			// Order of invalidation is immaterial
sl@0
   719
			while (count--)
sl@0
   720
				{
sl@0
   721
				InvalidateRect(iHwnd, &iPostedRect[count], FALSE);
sl@0
   722
				}
sl@0
   723
sl@0
   724
			iPostedRectCount = 0;
sl@0
   725
			}
sl@0
   726
		else
sl@0
   727
			{
sl@0
   728
			InvalidateRect(iHwnd, NULL, FALSE);
sl@0
   729
			}
sl@0
   730
sl@0
   731
		// Use differences to allow for wraparound
sl@0
   732
		if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0)
sl@0
   733
			{
sl@0
   734
			// Post waited for is now being displayed or was dropped
sl@0
   735
			iWaitForPostRequest.Complete(KErrNone);
sl@0
   736
			}
sl@0
   737
		iLastPostCount = iPostCount;
sl@0
   738
		}
sl@0
   739
	}
sl@0
   740
sl@0
   741
sl@0
   742
/**
sl@0
   743
Set the status object for this request and the thread to complete it on, if not
sl@0
   744
already set.
sl@0
   745
@param aStatus	The new request status.
sl@0
   746
@param aThread	The thread on which to complete.
sl@0
   747
@return EFalse if the status is already set, or ETrue if the status has now been
sl@0
   748
set.
sl@0
   749
*/
sl@0
   750
TBool DDisplayChannel::TRequest::SetStatus(TThreadMessage& aMsg)
sl@0
   751
	{
sl@0
   752
	if (iStatus)
sl@0
   753
		{
sl@0
   754
		__ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnSet));
sl@0
   755
		return EFalse;	// In use
sl@0
   756
		}
sl@0
   757
sl@0
   758
	__ASSERT_DEBUG(!iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadAlreadySet));
sl@0
   759
	DThread* thread = aMsg.Client();
sl@0
   760
	TInt r = thread->Open();
sl@0
   761
	__ASSERT_DEBUG( r == KErrNone, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadOpenFailed));
sl@0
   762
	(TAny)r;
sl@0
   763
	iThread = thread;
sl@0
   764
	iStatus = reinterpret_cast<TRequestStatus*>(aMsg.Ptr0());
sl@0
   765
	return ETrue;
sl@0
   766
	}
sl@0
   767
sl@0
   768
sl@0
   769
/**
sl@0
   770
Complete the request with the given result. If the status has not been set, or
sl@0
   771
has already been completed, this does nothing.
sl@0
   772
@param aResult	The result of the asynchronous request.
sl@0
   773
*/
sl@0
   774
void DDisplayChannel::TRequest::Complete(TInt aResult)
sl@0
   775
	{
sl@0
   776
	if (iStatus)
sl@0
   777
		{
sl@0
   778
    	__ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnComplete));
sl@0
   779
		Kern::RequestComplete(iThread, iStatus, aResult);
sl@0
   780
		Kern::SafeClose((DObject*&)iThread, NULL);
sl@0
   781
		}
sl@0
   782
	}
sl@0
   783
sl@0
   784
sl@0
   785
/**
sl@0
   786
Post the current composition buffer to the display on the next frame tick.
sl@0
   787
@param aRegion	NULL if the entire buffer has changed, or a user pointer to up
sl@0
   788
to TDisplayInfo::KMaxRectagles areas that have changed.
sl@0
   789
@param aPostCount	User pointer to an integer to receive the new post count.
sl@0
   790
@return KErrNone, or a system-wide error code
sl@0
   791
*/
sl@0
   792
TInt DDisplayChannel::PostCompositionBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
sl@0
   793
	{
sl@0
   794
	if (!IsCompositionBuffer(iGetBuffer))
sl@0
   795
		{
sl@0
   796
		return KErrNotSupported;
sl@0
   797
		}
sl@0
   798
sl@0
   799
	if (iWaitForPost == iPostCount)
sl@0
   800
		{
sl@0
   801
		// Complete wait for post (dropped)
sl@0
   802
		iWaitForPostRequest.Complete(KErrNone);
sl@0
   803
		}
sl@0
   804
sl@0
   805
	if (IsUserBuffer(iPostedBuffer))
sl@0
   806
		{
sl@0
   807
		// Complete the user post request (not displayed)
sl@0
   808
		iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
sl@0
   809
		}
sl@0
   810
sl@0
   811
	iPostedBuffer = iGetBuffer;
sl@0
   812
	iGetBuffer = NextCompositionBuffer(iGetBuffer);
sl@0
   813
sl@0
   814
	if (iNumCompositionBuffers > 2 && iGetBuffer == iDisplayBuffer)
sl@0
   815
		{
sl@0
   816
		// With more than two buffers, there must always be one available with
sl@0
   817
		// no waiting required, so find it.
sl@0
   818
		iGetBuffer = NextCompositionBuffer(iGetBuffer);
sl@0
   819
		}
sl@0
   820
sl@0
   821
	// Get the region
sl@0
   822
	if (aRegion)
sl@0
   823
		{
sl@0
   824
		// Set iPostedRect(Count) from aRegion.
sl@0
   825
		Panic(EDisplayPanicNotYetImplemented);
sl@0
   826
		}
sl@0
   827
sl@0
   828
	// What to do about wrapping?
sl@0
   829
	iPostCount++;
sl@0
   830
	iNewRotation = iCurrentRotation;
sl@0
   831
	iNewResolution = iCurrentResolution;
sl@0
   832
	iNewBufferFormat = iCurrentBufferFormat;
sl@0
   833
	SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
sl@0
   834
sl@0
   835
	return KErrNone;
sl@0
   836
	}
sl@0
   837
sl@0
   838
sl@0
   839
/**
sl@0
   840
Post the legacy buffer to the display on the next frame tick.
sl@0
   841
@param aRegion	NULL if the entire buffer has changed, or a user pointer to up
sl@0
   842
to TDisplayInfo::KMaxRectagles areas that have changed.
sl@0
   843
@param aPostCount	User pointer to an integer to receive the new post count.
sl@0
   844
@return KErrNone, or a system-wide error code
sl@0
   845
*/
sl@0
   846
TInt DDisplayChannel::PostLegacyBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
sl@0
   847
	{
sl@0
   848
	if (iWaitForPost == iPostCount)
sl@0
   849
		{
sl@0
   850
		// Complete wait for post (dropped)
sl@0
   851
		iWaitForPostRequest.Complete(KErrNone);
sl@0
   852
		}
sl@0
   853
sl@0
   854
	if (IsUserBuffer(iPostedBuffer))
sl@0
   855
		{
sl@0
   856
		iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
sl@0
   857
		}
sl@0
   858
sl@0
   859
	// iBuffer should NOT be NULL here!
sl@0
   860
	__ASSERT_ALWAYS(iBuffer[KLegacyBuffer].iAddress, Panic(EDisplayPanicNoLegacyBuffer));
sl@0
   861
	iPostedBuffer = KLegacyBuffer;
sl@0
   862
sl@0
   863
	// Get the region into iRegion
sl@0
   864
	if (aRegion)
sl@0
   865
		{
sl@0
   866
		// Set iPostedRect(Count) from aRegion.
sl@0
   867
		Panic(EDisplayPanicNotYetImplemented);
sl@0
   868
		}
sl@0
   869
sl@0
   870
	iPostCount++;
sl@0
   871
	iNewRotation = iCurrentRotation;
sl@0
   872
	iNewResolution = iCurrentResolution;
sl@0
   873
	iNewBufferFormat = iCurrentBufferFormat;
sl@0
   874
	SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
sl@0
   875
sl@0
   876
	return KErrNone;
sl@0
   877
	}
sl@0
   878
sl@0
   879
sl@0
   880
/**
sl@0
   881
Asynchronously request the current composition buffer. Completes immediately
sl@0
   882
if not already being displayed, or an error occurs.
sl@0
   883
@param aStatus	The request status to be completed.
sl@0
   884
@param aAddress	The user pointer to the location to put the address.
sl@0
   885
*/
sl@0
   886
TInt DDisplayChannel::GetCompositionBuffer(TAny** aAddress)
sl@0
   887
	{
sl@0
   888
	if (!IsCompositionBuffer(iGetBuffer))
sl@0
   889
		{
sl@0
   890
		// No composition buffers available for use.
sl@0
   891
		return KErrNotSupported;
sl@0
   892
		}
sl@0
   893
sl@0
   894
	// The address won't change, so may as well set it now.
sl@0
   895
	TUint idx = iGetBuffer - KFirstCompositionBuffer;
sl@0
   896
	if (SafePut(aAddress, &idx, sizeof(TUint)) != KErrNone)
sl@0
   897
		{
sl@0
   898
		return KErrArgument;
sl@0
   899
		}
sl@0
   900
sl@0
   901
	if (iNumCompositionBuffers > 1 && iGetBuffer == iDisplayBuffer)
sl@0
   902
		{
sl@0
   903
		// Multi-buffer case, and buffer is currently being displayed
sl@0
   904
sl@0
   905
		if (iBuffer[iGetBuffer].iRequest.SetStatus(*iMsg))
sl@0
   906
			{
sl@0
   907
			return KRequestPending;
sl@0
   908
			}
sl@0
   909
sl@0
   910
		// Already set
sl@0
   911
		return KErrInUse;
sl@0
   912
		}
sl@0
   913
sl@0
   914
	return KErrNone;
sl@0
   915
	}
sl@0
   916
sl@0
   917
sl@0
   918
/**
sl@0
   919
Post a user buffer to the display on the next frame tick.
sl@0
   920
@param aBufferId	The ID of the user buffer to post.
sl@0
   921
@param aRegion	NULL if the entire buffer has changed, or a user pointer to up
sl@0
   922
to TDisplayInfo::KMaxRectagles areas that have changed.
sl@0
   923
@return KErrNone, or a system-wide error code
sl@0
   924
*/
sl@0
   925
TInt DDisplayChannel::PostUserBuffer(RDisplayChannel::TBufferId* aBufferId, TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
sl@0
   926
	{
sl@0
   927
	RDisplayChannel::TBufferId bufferId;
sl@0
   928
	bufferId = reinterpret_cast <RDisplayChannel::TBufferId> (aBufferId);
sl@0
   929
sl@0
   930
	if (!IsUserBuffer(bufferId))
sl@0
   931
		{
sl@0
   932
		// Not a user buffer.
sl@0
   933
		return KErrArgument;
sl@0
   934
		}
sl@0
   935
sl@0
   936
	if (!iBuffer[bufferId].iChunk)
sl@0
   937
		{
sl@0
   938
		// User buffer not initialised.
sl@0
   939
		return KErrArgument;
sl@0
   940
		}
sl@0
   941
sl@0
   942
	if (iWaitForPost == iPostCount)
sl@0
   943
		{
sl@0
   944
		// Complete wait for post (dropped)
sl@0
   945
		iWaitForPostRequest.Complete(KErrNone);
sl@0
   946
		}
sl@0
   947
sl@0
   948
	if (IsUserBuffer(iPostedBuffer))
sl@0
   949
		{
sl@0
   950
		// Complete the user post request (not displayed)
sl@0
   951
		iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
sl@0
   952
		}
sl@0
   953
sl@0
   954
	if (bufferId == iDisplayBuffer)	//pathological case
sl@0
   955
		{
sl@0
   956
		// Complete the current display buffer as we are superceding it with the same one
sl@0
   957
		iBuffer[bufferId].iRequest.Complete(KErrNone);
sl@0
   958
		}
sl@0
   959
sl@0
   960
	// Only one buffer can be posted at any time, and if it were this user
sl@0
   961
	// buffer, the request will have just been completed, so this shouldn't fail.
sl@0
   962
	TBool isSet = iBuffer[bufferId].iRequest.SetStatus(*iMsg);
sl@0
   963
sl@0
   964
	__ASSERT_DEBUG(isSet, Panic(EDisplayPanicInUse));
sl@0
   965
	(TAny)isSet;
sl@0
   966
	iPostedBuffer = bufferId;
sl@0
   967
sl@0
   968
	// Get the region
sl@0
   969
	if (aRegion)
sl@0
   970
		{
sl@0
   971
		// Set iPostedRect(Count) from aRegion.
sl@0
   972
		Panic(EDisplayPanicNotYetImplemented);
sl@0
   973
		}
sl@0
   974
sl@0
   975
	iPostCount++;
sl@0
   976
	iNewRotation = iCurrentRotation;
sl@0
   977
	iNewResolution = iCurrentResolution;
sl@0
   978
	iNewBufferFormat = iCurrentBufferFormat;
sl@0
   979
	SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
sl@0
   980
sl@0
   981
	return KRequestPending;
sl@0
   982
	}
sl@0
   983
sl@0
   984
/**
sl@0
   985
Asynchronous request notification when the given post count is reached (or
sl@0
   986
passed).
sl@0
   987
@param aStatus	The request status to be completed.
sl@0
   988
@param aPostCount	The count to wait for.
sl@0
   989
*/
sl@0
   990
TInt DDisplayChannel::WaitForPost(RDisplayChannel::TPostCount* aPostCount)
sl@0
   991
	{
sl@0
   992
	TInt postCount;
sl@0
   993
sl@0
   994
	kumemget(&postCount, aPostCount, sizeof(RDisplayChannel::TPostCount));
sl@0
   995
sl@0
   996
	if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0)
sl@0
   997
		{
sl@0
   998
		// Set up the request to be completed when the post occurs
sl@0
   999
		if (iWaitForPostRequest.SetStatus(*iMsg))
sl@0
  1000
			{
sl@0
  1001
			iWaitForPost = postCount;
sl@0
  1002
			return KRequestPending;
sl@0
  1003
			}
sl@0
  1004
sl@0
  1005
		// Already waiting for a post
sl@0
  1006
		return KErrInUse;
sl@0
  1007
		}
sl@0
  1008
sl@0
  1009
	// Requested post already displayed/dropped
sl@0
  1010
	return KErrNone;
sl@0
  1011
	}
sl@0
  1012
sl@0
  1013
/**
sl@0
  1014
Asynchronous request notification when the display connection state changes.
sl@0
  1015
This occurs when the display is disconnected, connected with no list, or a list of modes becomes available or is updated.
sl@0
  1016
*/
sl@0
  1017
TInt DDisplayChannel::WaitForDisplayConnect()
sl@0
  1018
	{
sl@0
  1019
	
sl@0
  1020
	Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &iDisplayStateSpinner, NULL, iScreenNumber);
sl@0
  1021
	
sl@0
  1022
	if (iWaitForDisplayConnect.SetStatus(*iMsg))
sl@0
  1023
		{
sl@0
  1024
		return KRequestPending;
sl@0
  1025
		}
sl@0
  1026
sl@0
  1027
	// Already waiting for a post
sl@0
  1028
	return KErrInUse;
sl@0
  1029
	}
sl@0
  1030
sl@0
  1031
sl@0
  1032
/**
sl@0
  1033
Set the rotation of the screen on the next frame. If the buffer contents will
sl@0
  1034
not be valid, the flag set. The validity of the buffer is down to whether the
sl@0
  1035
width and height change.
sl@0
  1036
sl@0
  1037
@param aNewRotation	Address in user space of the new rotation setting.
sl@0
  1038
@param aDisplayConfigChanged	Address in user space of where to put whether the
sl@0
  1039
orientation specific info to use has changed following the rotation setting.
sl@0
  1040
@return KErrNone, or KErrArgument if an argument was invalid.
sl@0
  1041
*/
sl@0
  1042
TInt DDisplayChannel::SetRotation(RDisplayChannel::TDisplayRotation* aNewRotation,
sl@0
  1043
		TBool* aDisplayConfigChanged)
sl@0
  1044
	{
sl@0
  1045
	RDisplayChannel::TDisplayRotation newRotation;
sl@0
  1046
sl@0
  1047
	__ASSERT_DEBUG(aNewRotation, Panic(EDisplayPanicNullArgument));
sl@0
  1048
sl@0
  1049
	kumemget(&newRotation, aNewRotation, sizeof(newRotation));
sl@0
  1050
sl@0
  1051
	if (((TInt)newRotation - 1) & newRotation)
sl@0
  1052
		{
sl@0
  1053
		// More than one bit is set, which is not valid
sl@0
  1054
		return KErrArgument;
sl@0
  1055
		}
sl@0
  1056
sl@0
  1057
	if ((iChannelInfo.iAvailableRotations & newRotation) == 0)
sl@0
  1058
		{
sl@0
  1059
		// Rotation is not supported
sl@0
  1060
		return KErrArgument;
sl@0
  1061
		}
sl@0
  1062
sl@0
  1063
	TBool displayConfigChanged = (IsFlipped(newRotation) != IsFlipped(iCurrentRotation));
sl@0
  1064
	iCurrentRotation = newRotation;
sl@0
  1065
sl@0
  1066
	SafePut(aDisplayConfigChanged, &displayConfigChanged, sizeof(TBool));
sl@0
  1067
sl@0
  1068
	return KErrNone;
sl@0
  1069
	}
sl@0
  1070
sl@0
  1071
sl@0
  1072
/**
sl@0
  1073
Register a user buffer. Assign an ID for it (if available) and open the chunk to
sl@0
  1074
get the address.
sl@0
  1075
@param aChunkHandle	The chunk handle.
sl@0
  1076
@param aOffset		The offset from the chunk base address to the start of the
sl@0
  1077
buffer.
sl@0
  1078
@param aBufferId	The address in user space of where to put the buffer ID.
sl@0
  1079
*/
sl@0
  1080
TInt DDisplayChannel::RegisterUserBuffer(TInt aChunkHandle, TInt aOffset,
sl@0
  1081
		RDisplayChannel::TBufferId* aBufferId)
sl@0
  1082
	{
sl@0
  1083
	if (!aBufferId)
sl@0
  1084
		{
sl@0
  1085
		return KErrArgument;
sl@0
  1086
		}
sl@0
  1087
sl@0
  1088
	NKern::ThreadEnterCS();
sl@0
  1089
	DChunk* chunk = Kern::OpenSharedChunk(iMsg->Client(), aChunkHandle,
sl@0
  1090
			EFalse);
sl@0
  1091
	NKern::ThreadLeaveCS();
sl@0
  1092
	if (!chunk)
sl@0
  1093
		{
sl@0
  1094
		return KErrBadHandle;
sl@0
  1095
		}
sl@0
  1096
sl@0
  1097
	TLinAddr kernelAddress;
sl@0
  1098
sl@0
  1099
	const TInt bufferSize = (iDisplayResolution.iWidth * iDisplayResolution.iHeight);
sl@0
  1100
	TInt r = Kern::ChunkAddress(chunk,aOffset,bufferSize,kernelAddress);
sl@0
  1101
	if(r!=KErrNone)
sl@0
  1102
		{
sl@0
  1103
		NKern::ThreadEnterCS();
sl@0
  1104
		Kern::ChunkClose(chunk);
sl@0
  1105
		NKern::ThreadLeaveCS();
sl@0
  1106
		return r;
sl@0
  1107
		}
sl@0
  1108
sl@0
  1109
	// Search for an empty slot
sl@0
  1110
	for (TInt index = KFirstUserBuffer; index < (KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers); index++)
sl@0
  1111
		{
sl@0
  1112
		if (!iBuffer[index].iChunk)
sl@0
  1113
			{
sl@0
  1114
			// Found one, so fill in the details and return the index as the ID.
sl@0
  1115
			iBuffer[index].iChunk = chunk;
sl@0
  1116
			iBuffer[index].iAddress = (TAny*)(kernelAddress);
sl@0
  1117
			kumemput(aBufferId, &index, sizeof(RDisplayChannel::TBufferId));
sl@0
  1118
			return KErrNone;
sl@0
  1119
			}
sl@0
  1120
		}
sl@0
  1121
sl@0
  1122
	// No slots available.
sl@0
  1123
	NKern::ThreadEnterCS();
sl@0
  1124
	Kern::ChunkClose(chunk);
sl@0
  1125
	NKern::ThreadLeaveCS();
sl@0
  1126
	return KErrTooBig;
sl@0
  1127
	}
sl@0
  1128
sl@0
  1129
sl@0
  1130
/**
sl@0
  1131
Deregister a user buffer.
sl@0
  1132
@param aBufferId	The buffer ID.
sl@0
  1133
*/
sl@0
  1134
TInt DDisplayChannel::DeregisterUserBuffer(RDisplayChannel::TBufferId* aBufferId)
sl@0
  1135
	{
sl@0
  1136
	RDisplayChannel::TBufferId bufferId;
sl@0
  1137
	
sl@0
  1138
	__ASSERT_DEBUG(aBufferId, Panic(EDisplayPanicNullArgument));
sl@0
  1139
	kumemget(&bufferId, aBufferId, sizeof(RDisplayChannel::TBufferId));
sl@0
  1140
sl@0
  1141
	if (!IsUserBuffer(bufferId))
sl@0
  1142
		{
sl@0
  1143
		// Not a valid ID
sl@0
  1144
		return KErrArgument;
sl@0
  1145
		}
sl@0
  1146
sl@0
  1147
	TBufferInfo* buffer = &iBuffer[bufferId];
sl@0
  1148
	if (!buffer->iChunk)
sl@0
  1149
		{
sl@0
  1150
		// Not registered
sl@0
  1151
		return KErrArgument;
sl@0
  1152
		}
sl@0
  1153
sl@0
  1154
	if (iDisplayBuffer == bufferId)
sl@0
  1155
		{
sl@0
  1156
		return KErrInUse;
sl@0
  1157
		}
sl@0
  1158
sl@0
  1159
	if (iPostedBuffer == bufferId)
sl@0
  1160
		{
sl@0
  1161
		// Was queued to be posted
sl@0
  1162
		iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet;
sl@0
  1163
		iPostedRectCount = 0;
sl@0
  1164
		}
sl@0
  1165
sl@0
  1166
	// Cancel any outstanding request on the buffer and clear out the fields.
sl@0
  1167
	buffer->iRequest.Complete(KErrCancel);
sl@0
  1168
	NKern::ThreadEnterCS();
sl@0
  1169
	Kern::ChunkClose(buffer->iChunk);
sl@0
  1170
	NKern::ThreadLeaveCS();
sl@0
  1171
	buffer->iChunk = NULL;
sl@0
  1172
	buffer->iAddress = NULL;
sl@0
  1173
sl@0
  1174
	return KErrNone;
sl@0
  1175
	}
sl@0
  1176
sl@0
  1177
/**
sl@0
  1178
Get all resolutions available for this screen and insert to a descriptor
sl@0
  1179
@return KErrNone if successful, otherwise a system wide error code.
sl@0
  1180
*/
sl@0
  1181
TInt DDisplayChannel::GetResolutions()
sl@0
  1182
	{
sl@0
  1183
	TInt r;
sl@0
  1184
	__ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
sl@0
  1185
	__ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
sl@0
  1186
	//get the number of resolutions (as above)
sl@0
  1187
	TInt numberOfResolutions = 0;
sl@0
  1188
	TInt refStateSpinner, curStateSpinner;
sl@0
  1189
	//Get the number of resolutions as well as the display state spinner at this point
sl@0
  1190
	r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &refStateSpinner, iScreenNumber);
sl@0
  1191
	if(r < KErrNone)
sl@0
  1192
		{
sl@0
  1193
		return r;
sl@0
  1194
		}
sl@0
  1195
		    	
sl@0
  1196
	TInt length;
sl@0
  1197
	TInt maxLength;
sl@0
  1198
	Kern::KUDesInfo(*(const TDesC*)iMsg->Ptr0(),length,maxLength);
sl@0
  1199
		    	
sl@0
  1200
	if ((maxLength/static_cast<TInt>(sizeof(RDisplayChannel::TResolution))) < numberOfResolutions)
sl@0
  1201
		{
sl@0
  1202
		return KErrOverflow;
sl@0
  1203
		}
sl@0
  1204
		    	
sl@0
  1205
	TVideoInfoV01 info;
sl@0
  1206
	TPckg<TVideoInfoV01> infoPckg(info);
sl@0
  1207
	RDisplayChannel::TResolution resolution = {{0,0},{0,0},RDisplayChannel::ERotationAll};
sl@0
  1208
	TPtr8 tempDes(NULL,0);
sl@0
  1209
sl@0
  1210
	TInt i;
sl@0
  1211
	for (i=0;i<numberOfResolutions;i++)
sl@0
  1212
		{
sl@0
  1213
		//before filling the package, the display state needs to be checked for consistency
sl@0
  1214
		Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &curStateSpinner, NULL, iScreenNumber);
sl@0
  1215
		    			    		
sl@0
  1216
		if(curStateSpinner != refStateSpinner)
sl@0
  1217
			{ //display state has changed, the resolution list we trying to get becomes corrupted
sl@0
  1218
			Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
sl@0
  1219
			return KErrCorrupt;
sl@0
  1220
			}
sl@0
  1221
sl@0
  1222
		//pass info package to be filled in, also sending the config to read, and the screen within that
sl@0
  1223
		Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber);
sl@0
  1224
		//save resolution
sl@0
  1225
		resolution.iPixelSize = info.iSizeInPixels;
sl@0
  1226
		resolution.iTwipsSize = info.iSizeInTwips;
sl@0
  1227
		//copy resolution
sl@0
  1228
  		tempDes.Set((TUint8*)&resolution,sizeof(RDisplayChannel::TResolution),sizeof(RDisplayChannel::TResolution));
sl@0
  1229
   		r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(),tempDes,i*sizeof(RDisplayChannel::TResolution),iMsg->Client());
sl@0
  1230
		    		
sl@0
  1231
   		if (r<KErrNone)
sl@0
  1232
   			{
sl@0
  1233
   			Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
sl@0
  1234
   			return r;
sl@0
  1235
   			}
sl@0
  1236
   		}
sl@0
  1237
	Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
sl@0
  1238
   	SafePut(iMsg->Ptr1(), &numberOfResolutions, sizeof(numberOfResolutions));
sl@0
  1239
   	return KErrNone;
sl@0
  1240
	}
sl@0
  1241
sl@0
  1242
sl@0
  1243
sl@0
  1244
TInt DDisplayChannel::SetResolution(TSize* aSize)
sl@0
  1245
	{
sl@0
  1246
	if (!aSize)
sl@0
  1247
		{
sl@0
  1248
		ClientPanic(RDisplayChannel::ENullArgument);
sl@0
  1249
		return KErrArgument;
sl@0
  1250
		}
sl@0
  1251
sl@0
  1252
	TSize size;
sl@0
  1253
	kumemget32(&size, aSize, sizeof(size));
sl@0
  1254
	if (size.iWidth < 0 || size.iHeight < 0)
sl@0
  1255
		{
sl@0
  1256
		ClientPanic(RDisplayChannel::EInvalidResolution);
sl@0
  1257
		return KErrArgument;
sl@0
  1258
		}
sl@0
  1259
	
sl@0
  1260
	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
sl@0
  1261
			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
sl@0
  1262
		{
sl@0
  1263
		return KErrPermissionDenied;
sl@0
  1264
		}
sl@0
  1265
sl@0
  1266
	// Validate size. Return KErrArgument on failure.
sl@0
  1267
	//Get the number of resolutions
sl@0
  1268
	TInt numberOfResolutions;
sl@0
  1269
	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber);
sl@0
  1270
	if(r < KErrNone)
sl@0
  1271
		{
sl@0
  1272
		return r;
sl@0
  1273
		}
sl@0
  1274
	TVideoInfoV01 info;
sl@0
  1275
	TPckg<TVideoInfoV01> infoPckg(info);
sl@0
  1276
	for (TInt i = 0; i < numberOfResolutions; i++)
sl@0
  1277
		{
sl@0
  1278
		//pass info package to be filled in, also sending the config to read, and the screen within that
sl@0
  1279
		Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber);
sl@0
  1280
		
sl@0
  1281
		if (info.iSizeInPixels.iWidth == size.iWidth &&
sl@0
  1282
				info.iSizeInPixels.iHeight == size.iHeight)
sl@0
  1283
			{	//matched resolution
sl@0
  1284
			iCurrentResolution = size;
sl@0
  1285
			iCurrentTwips = info.iSizeInTwips;
sl@0
  1286
			
sl@0
  1287
			if (iCurrentResolution.iHeight > iNewBufferFormat.iSize.iHeight ||
sl@0
  1288
				iCurrentResolution.iWidth > iNewBufferFormat.iSize.iWidth)
sl@0
  1289
				{
sl@0
  1290
				// going back to initial settings and, we hope, 
sl@0
  1291
				// the buffers could still be displayed correctly, but we have no guarantee
sl@0
  1292
				iCurrentBufferFormat = iInitialBufferFormat;
sl@0
  1293
				}
sl@0
  1294
			return KErrNone;
sl@0
  1295
			}
sl@0
  1296
   		}
sl@0
  1297
	return KErrArgument;	//if reached here, it did not match aSize to any config resolution
sl@0
  1298
	}
sl@0
  1299
sl@0
  1300
TInt DDisplayChannel::GetResolution(TSize* aSize)
sl@0
  1301
	{
sl@0
  1302
	TInt numberOfResolutions;
sl@0
  1303
	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions,
sl@0
  1304
			&numberOfResolutions, NULL, iScreenNumber);
sl@0
  1305
sl@0
  1306
	if (r == KErrNone)
sl@0
  1307
		{
sl@0
  1308
		if (numberOfResolutions > 0)
sl@0
  1309
			{
sl@0
  1310
		   	SafePut(aSize, &iCurrentResolution, sizeof(iCurrentResolution));
sl@0
  1311
			}
sl@0
  1312
		else
sl@0
  1313
			{
sl@0
  1314
			TSize resolution = {0,0};
sl@0
  1315
		   	SafePut(aSize, &resolution, sizeof(resolution));
sl@0
  1316
			}
sl@0
  1317
		}
sl@0
  1318
	return r;
sl@0
  1319
	}
sl@0
  1320
sl@0
  1321
TInt DDisplayChannel::GetTwips(TSize* aSize)
sl@0
  1322
	{
sl@0
  1323
	TInt numberOfResolutions;
sl@0
  1324
	TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions,
sl@0
  1325
			&numberOfResolutions, NULL, iScreenNumber);
sl@0
  1326
sl@0
  1327
	if (r == KErrNone)
sl@0
  1328
		{
sl@0
  1329
		if (numberOfResolutions > 0)
sl@0
  1330
			{
sl@0
  1331
		   	SafePut(aSize, &iCurrentTwips, sizeof(iCurrentTwips));
sl@0
  1332
			}
sl@0
  1333
		else
sl@0
  1334
			{
sl@0
  1335
			TSize twips = {0,0};
sl@0
  1336
		   	SafePut(aSize, &twips, sizeof(twips));
sl@0
  1337
			}
sl@0
  1338
		}
sl@0
  1339
	return r;
sl@0
  1340
	}
sl@0
  1341
/**
sl@0
  1342
Get all the pixel formats available and insert them to a descriptor
sl@0
  1343
@return KErrNone if successful, otherwise a system wide error code.
sl@0
  1344
*/
sl@0
  1345
TInt DDisplayChannel::GetPixelFormats()
sl@0
  1346
	{
sl@0
  1347
	TInt r;
sl@0
  1348
	__ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
sl@0
  1349
	__ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
sl@0
  1350
	//get the number of resolutions (as above)
sl@0
  1351
	TPtr8 pixelFormatDes(NULL,0);
sl@0
  1352
	TInt length = ((TInt)sizeof(RDisplayChannel::TPixelFormat)) * iPixelFormatArraySize;
sl@0
  1353
	pixelFormatDes.Set((TUint8*)iPixelFormatArray, length, length);
sl@0
  1354
	r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(), pixelFormatDes, 0, iMsg->Client());
sl@0
  1355
	if (r == KErrNone)
sl@0
  1356
		{
sl@0
  1357
		Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(), length);
sl@0
  1358
		SafePut(iMsg->Ptr1(), &iPixelFormatArraySize, sizeof(iPixelFormatArraySize));
sl@0
  1359
		}
sl@0
  1360
	return r;
sl@0
  1361
	}
sl@0
  1362
sl@0
  1363
sl@0
  1364
TInt DDisplayChannel::SetBufferFormat(RDisplayChannel::TBufferFormat* aBufferFormat)
sl@0
  1365
	{
sl@0
  1366
	if (!aBufferFormat)
sl@0
  1367
		{
sl@0
  1368
		ClientPanic(RDisplayChannel::ENullArgument);
sl@0
  1369
		return KErrArgument;
sl@0
  1370
		}
sl@0
  1371
sl@0
  1372
	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
sl@0
  1373
			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
sl@0
  1374
		{
sl@0
  1375
		return KErrPermissionDenied;
sl@0
  1376
		}
sl@0
  1377
sl@0
  1378
	RDisplayChannel::TBufferFormat bufferFormat;
sl@0
  1379
	kumemget32(&bufferFormat, aBufferFormat, sizeof(RDisplayChannel::TBufferFormat));
sl@0
  1380
	
sl@0
  1381
	// Validate Size
sl@0
  1382
	if (iCurrentResolution.iHeight > bufferFormat.iSize.iHeight ||
sl@0
  1383
		iCurrentResolution.iWidth > bufferFormat.iSize.iWidth ||
sl@0
  1384
		bufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth ||
sl@0
  1385
		bufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth)
sl@0
  1386
		{
sl@0
  1387
		//return error on failure
sl@0
  1388
		return KErrArgument;
sl@0
  1389
		}
sl@0
  1390
	
sl@0
  1391
	// check we received one of the supported formats.
sl@0
  1392
	for (TInt i = 0; i < iPixelFormatArraySize; i++)
sl@0
  1393
		{
sl@0
  1394
		if (bufferFormat.iPixelFormat == iPixelFormatArray[i])
sl@0
  1395
			{
sl@0
  1396
			// the arguments are all validated at this point, update the current format
sl@0
  1397
			iCurrentBufferFormat = bufferFormat;
sl@0
  1398
			return KErrNone;
sl@0
  1399
			}
sl@0
  1400
		}
sl@0
  1401
	
sl@0
  1402
		//return error on failure
sl@0
  1403
		return KErrArgument;
sl@0
  1404
	}
sl@0
  1405
sl@0
  1406
TInt DDisplayChannel::ValidateBufferFormat(const RDisplayChannel::TBufferFormat& aBufferFormat,
sl@0
  1407
									 	   const RDisplayChannel::TResolution& aResolution)
sl@0
  1408
	{
sl@0
  1409
	// Validate the size reported in buffer format against the given resolution
sl@0
  1410
	if (aResolution.iPixelSize.iHeight > aBufferFormat.iSize.iHeight ||
sl@0
  1411
		aResolution.iPixelSize.iWidth > aBufferFormat.iSize.iWidth ||
sl@0
  1412
		aBufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth ||
sl@0
  1413
		aBufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth)
sl@0
  1414
		{
sl@0
  1415
		//return error on failure
sl@0
  1416
		return KErrArgument;
sl@0
  1417
		}
sl@0
  1418
	
sl@0
  1419
	// check we received one of the supported formats.
sl@0
  1420
	for (TInt i = 0; i < iPixelFormatArraySize; i++)
sl@0
  1421
		{
sl@0
  1422
		if (aBufferFormat.iPixelFormat == iPixelFormatArray[i])
sl@0
  1423
			{
sl@0
  1424
			return KErrNone;
sl@0
  1425
			}
sl@0
  1426
		}
sl@0
  1427
		
sl@0
  1428
	return KErrArgument;
sl@0
  1429
	}
sl@0
  1430
sl@0
  1431
TInt DDisplayChannel::NextPlaneOffset(RDisplayChannel::TBufferFormat* aBufferFormat, 
sl@0
  1432
		            				 RDisplayChannel::TBufferFormatContext* aContext)
sl@0
  1433
	{
sl@0
  1434
	if (!aBufferFormat)
sl@0
  1435
		{
sl@0
  1436
		ClientPanic(RDisplayChannel::ENullArgument);
sl@0
  1437
		return KErrArgument;
sl@0
  1438
		}
sl@0
  1439
sl@0
  1440
	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
sl@0
  1441
			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
sl@0
  1442
		{
sl@0
  1443
		return KErrPermissionDenied;
sl@0
  1444
		}
sl@0
  1445
sl@0
  1446
	RDisplayChannel::TBufferFormat bufferFormat;
sl@0
  1447
	kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat));
sl@0
  1448
	
sl@0
  1449
	RDisplayChannel::TResolution resolution;
sl@0
  1450
	RDisplayChannel::TDisplayRotation rotation;
sl@0
  1451
	
sl@0
  1452
	if (aContext)
sl@0
  1453
		{
sl@0
  1454
		RDisplayChannel::TBufferFormatContext context;
sl@0
  1455
		kumemget32(&context, aContext, sizeof(context));
sl@0
  1456
		resolution = context.iResolution;
sl@0
  1457
		rotation = context.iRotation;
sl@0
  1458
		}
sl@0
  1459
	else
sl@0
  1460
		{
sl@0
  1461
		resolution.iPixelSize = iCurrentResolution;
sl@0
  1462
		rotation = iCurrentRotation;
sl@0
  1463
		}
sl@0
  1464
	
sl@0
  1465
		TInt err = ValidateBufferFormat(bufferFormat, resolution);
sl@0
  1466
		
sl@0
  1467
		if (err != KErrNone)
sl@0
  1468
			{
sl@0
  1469
			return err;
sl@0
  1470
			}
sl@0
  1471
		//it assumes no planar pixel formats are supported by this driver implementation
sl@0
  1472
		return 0;
sl@0
  1473
	}
sl@0
  1474
sl@0
  1475
TInt DDisplayChannel::NextLineOffset(RDisplayChannel::TBufferFormat* aBufferFormat, 
sl@0
  1476
		            				 RDisplayChannel::TBufferFormatContext* aContext)
sl@0
  1477
	{
sl@0
  1478
	if (!aBufferFormat)
sl@0
  1479
		{
sl@0
  1480
		ClientPanic(RDisplayChannel::ENullArgument);
sl@0
  1481
		return KErrArgument;
sl@0
  1482
		}
sl@0
  1483
sl@0
  1484
	if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, 
sl@0
  1485
			__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
sl@0
  1486
		{
sl@0
  1487
		return KErrPermissionDenied;
sl@0
  1488
		}
sl@0
  1489
sl@0
  1490
	RDisplayChannel::TBufferFormat bufferFormat;
sl@0
  1491
	kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat));
sl@0
  1492
	
sl@0
  1493
	RDisplayChannel::TResolution resolution;
sl@0
  1494
	RDisplayChannel::TDisplayRotation rotation;
sl@0
  1495
	
sl@0
  1496
	if (aContext)
sl@0
  1497
		{
sl@0
  1498
		RDisplayChannel::TBufferFormatContext context;
sl@0
  1499
		kumemget32(&context, aContext, sizeof(context));
sl@0
  1500
		resolution = context.iResolution;
sl@0
  1501
		rotation = context.iRotation;
sl@0
  1502
		}
sl@0
  1503
	else
sl@0
  1504
		{
sl@0
  1505
		resolution.iPixelSize = iCurrentResolution;
sl@0
  1506
		rotation = iCurrentRotation;
sl@0
  1507
		}
sl@0
  1508
sl@0
  1509
	TInt err = ValidateBufferFormat(bufferFormat, resolution);
sl@0
  1510
	
sl@0
  1511
	if (err != KErrNone)
sl@0
  1512
		{
sl@0
  1513
		return err;
sl@0
  1514
		}
sl@0
  1515
	
sl@0
  1516
	TInt bpp = 0;
sl@0
  1517
	//validating the pixel format and getting the pixel size in bits
sl@0
  1518
	switch (bufferFormat.iPixelFormat)
sl@0
  1519
		{
sl@0
  1520
		case EUidPixelFormatXRGB_4444:	// RGB4444
sl@0
  1521
		case EUidPixelFormatARGB_4444:
sl@0
  1522
		case EUidPixelFormatRGB_565:	// RGB565
sl@0
  1523
			bpp = 16;
sl@0
  1524
			break;
sl@0
  1525
		case EUidPixelFormatXRGB_8888:	// Really 32bpp, but top 8 unused
sl@0
  1526
		case EUidPixelFormatARGB_8888:
sl@0
  1527
		case EUidPixelFormatARGB_8888_PRE:
sl@0
  1528
			bpp = 32;
sl@0
  1529
			break;
sl@0
  1530
		default:
sl@0
  1531
			// We got an error, it seems. The pixel format is not supported 
sl@0
  1532
			// Let's panic because the pixel format has just been validated
sl@0
  1533
			Panic(EDisplayPanicInvalidBitDepth);
sl@0
  1534
			break;
sl@0
  1535
		}
sl@0
  1536
		
sl@0
  1537
	TInt widthInPixel = 0;	// pixels
sl@0
  1538
		
sl@0
  1539
	// let's take in consideration the given rotation
sl@0
  1540
	switch (rotation)
sl@0
  1541
		{
sl@0
  1542
		case RDisplayChannel::ERotation90CW:
sl@0
  1543
		case RDisplayChannel::ERotation270CW:
sl@0
  1544
			widthInPixel = bufferFormat.iSize.iHeight;
sl@0
  1545
			break;
sl@0
  1546
		default:	// Normal
sl@0
  1547
			widthInPixel = bufferFormat.iSize.iWidth;
sl@0
  1548
			break;
sl@0
  1549
		}
sl@0
  1550
	
sl@0
  1551
	// we have to round up to 32 bits word. This is a Ms Windows limitation 
sl@0
  1552
	TInt stride = _ALIGN_UP((widthInPixel * bpp), 32) >> 3;
sl@0
  1553
	return stride;
sl@0
  1554
	}