First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <kernel/kern_priv.h>
18 #include <kernel/kernel.h>
21 #include <pixelformats.h>
23 #include "display_chan.h"
25 #define WIN32_LEAN_AND_MEAN
26 #pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
28 #pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
31 #ifdef DD_TRACE_ENABLED
40 DDisplayChannel::DDisplayChannel() :
41 iVSync(&DDisplayChannel::VSyncTimerFn, this),
42 iVSyncDfc(&DDisplayChannel::VSyncDfcFn, this, Kern::DfcQue0(), KDfcPriority),
43 iPostedBuffer((TUint)KBufferNotSet),
44 iGetBuffer((TUint)KFirstCompositionBuffer),
45 iDisplayStateSpinner(0),
46 iVersion(KDisplayChMajorVersionNumber,
47 KDisplayChMinorVersionNumber,
48 KDisplayChBuildVersionNumber)
50 DD_TRACE(Kern::Printf("DDisplayChannel Creation");)
54 DDisplayChannel::~DDisplayChannel()
56 DD_TRACE(Kern::Printf("DDisplayChannel Destruction");)
59 NKern::ThreadEnterCS();
61 NKern::ThreadLeaveCS();
67 Second stage constructor called by the kernel's device driver framework.
68 This is called in the context of the user thread (client) which requested the creation of a Logical Channel
69 (E.g. through a call to RBusLogicalChannel::DoCreate)
70 The thread is in a critical section.
72 @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
73 @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
74 @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
76 @return KErrNone if successful, otherwise one of the other system wide error codes.
78 TInt DDisplayChannel::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
81 if (!Kern::QueryVersionSupported(iDevice->iVersion, aVer))
83 return KErrNotSupported;
86 iScreenNumber = aUnit; /*aUnit?*/
87 SetDfcQ(Kern::DfcQue0());
90 // Ask the GUI code to initialize the rest of the object.
91 return Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel,
92 (TAny*)iScreenNumber, this);
96 void DDisplayChannel::ValidateSpecificInfo(TInt aBytesPerPixel, RDisplayChannel::TOrientationSpecificInfo& aInfo)
98 __ASSERT_DEBUG(aInfo.iWidth > 0 && aInfo.iHeight > 0, Panic(EDisplayPanicInvalidDimensions));
99 __ASSERT_DEBUG(aInfo.iOffsetBetweenLines > 0, Panic(EDisplayPanicInvalidStride));
100 __ASSERT_DEBUG(aInfo.iWidth * aBytesPerPixel <= (TUint)aInfo.iOffsetBetweenLines, Panic(EDisplayPanicInvalidStride));
102 //this is just to stop compiler complaining..
103 (TAny)aBytesPerPixel;
108 Finish creating the display channel object.
110 @param aInfo Display description object
111 @param aRotation Initial rotation
112 @param aHwnd Associated window handle
113 @param aFrameBuffers Array of one or more pointers to frame buffers
114 @param aResolution Initial resolution
115 @param aTwips Size in twips
116 @return KErrNone if successful, or a system-wide error otherwise.
118 TInt DDisplayChannel::Initialize(RDisplayChannel::TDisplayInfo& aInfo,
119 RDisplayChannel::TDisplayRotation aRotation,
120 HWND aHwnd, RPointerArray<TAny>& aFrameBuffers,
121 RPointerArray<TBufferAddressA>& aChunks,
122 TScreenBuffer& aDsaBuffer,
125 const RDisplayChannel::TPixelFormat aPixelFormatArray[],
126 const TInt aPixelFormatArraySize,
127 const RDisplayChannel::TBufferFormat& aBufferFormat)
130 __ASSERT_DEBUG(aInfo.iBitsPerPixel >= 12 && aInfo.iBitsPerPixel <= 32, Panic(EDisplayPanicInvalidBitDepth));
131 __ASSERT_DEBUG(aInfo.iRefreshRateHz > 0, Panic(EDisplayPanicInvalidRefreshRate));
132 __ASSERT_DEBUG(aInfo.iAvailableRotations & aRotation, Panic(EDisplayPanicInvalidRotation));
133 __ASSERT_DEBUG(aInfo.iNormal.iWidth == aInfo.iFlipped.iHeight, Panic(EDisplayPanicInvalidDimensions));
134 __ASSERT_DEBUG(aInfo.iNormal.iHeight == aInfo.iFlipped.iWidth, Panic(EDisplayPanicInvalidDimensions));
135 __ASSERT_DEBUG(aRotation == RDisplayChannel::ERotationNormal ||
136 aRotation == RDisplayChannel::ERotation90CW ||
137 aRotation == RDisplayChannel::ERotation180 ||
138 aRotation == RDisplayChannel::ERotation270CW, Panic(EDisplayPanicInvalidRotation));
139 __ASSERT_DEBUG(aFrameBuffers.Count() > 0, Panic(EDisplayPanicInvalidFrameBuffers));
140 __ASSERT_DEBUG(aHwnd, Panic(EDisplayPanicInvalidWindowHandle));
142 ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iNormal);
143 ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iFlipped);
145 // aFrameBuffers includes the legacy buffer at index 0.
146 iNumCompositionBuffers = aFrameBuffers.Count() - 1;
147 iTotalBuffers = KFirstCompositionBuffer + iNumCompositionBuffers;
148 iBuffer = (TBufferInfo*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferInfo));
149 iChunks = (TBufferAddressA*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferAddressA));
155 aInfo.iNumCompositionBuffers = iNumCompositionBuffers;
156 for (TUint index = 0; index < iNumCompositionBuffers; index++)
158 iBuffer[index + KFirstCompositionBuffer].iAddress = aFrameBuffers[index + 1];
159 iChunks[index + KFirstCompositionBuffer].iChunk = aChunks[index + 1]->iChunk;
162 iChannelInfo = aInfo;
164 iDisplayRotation = iCurrentRotation = aRotation;
165 iDisplayResolution = iCurrentResolution = aResolution;
166 iCurrentTwips = aTwips;
169 // Ensure the VSync DFC is on the same queue as the message handling.
170 iVSyncTicks = NKern::TimerTicks(1000 / aInfo.iRefreshRateHz);
171 iVSync.OneShot(iVSyncTicks);
173 if (aDsaBuffer.iMemChunks.Count() != 0)
175 iBuffer[KLegacyBuffer].iAddress = aDsaBuffer.iFrameBuffers[0];
179 iBuffer[KLegacyBuffer].iAddress = NULL;
182 iPixelFormatArray = aPixelFormatArray;
183 iPixelFormatArraySize = aPixelFormatArraySize;
185 // copy the initial buffer format
186 iInitialBufferFormat = aBufferFormat;
187 iDisplayBufferFormat = iInitialBufferFormat;
188 iCurrentBufferFormat = iDisplayBufferFormat;
194 Set the address of the legacy buffer.
196 @param aAddress Pointer to the legacy buffer.
198 void DDisplayChannel::SetLegacyBuffer(void *aAddress)
200 iBuffer[KLegacyBuffer].iAddress = aAddress;
206 Handle a message on this display for the logical channel.
208 @param aMsg The message to process. The iValue member of this distinguishes the
210 iValue == ECloseMsg, channel close message
211 iValue == KMaxTInt, a 'DoCancel' message
212 iValue >= 0, a 'DoControl' message with function number equal to iValue
213 iValue < 0, a 'DoRequest' message with function number equal to ~iValue
215 void DDisplayChannel::HandleMsg(TMessageBase* aMsg)
217 iMsg = (TThreadMessage*)aMsg;
218 TInt id = iMsg->iValue;
221 if (id == (TInt)ECloseMsg)
224 iWaitForPostRequest.Complete(KErrCancel);
225 iWaitForDisplayConnect.Complete(KErrCancel);
228 // Unhook display channel from the GUI code if initialized.
229 if (iBuffer[KLegacyBuffer].iAddress)
231 Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel,
232 (TAny*)iScreenNumber, NULL);
233 PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0, 0);
234 InvalidateRect(iHwnd, NULL, FALSE);
237 RDisplayChannel::TBufferId index = iTotalBuffers;
241 iBuffer[index].iRequest.Complete(KErrCancel);
243 if (IsUserBuffer(index))
246 if (iBuffer[index].iChunk)
248 NKern::ThreadEnterCS();
249 Kern::ChunkClose(iBuffer[index].iChunk);
250 NKern::ThreadLeaveCS();
256 iMsg->Complete(KErrNone, EFalse);
267 r = (id == KMaxTInt) ? DoCancel(iMsg->Int0()) : DoControl(id);
270 iMsg->Complete(r, (id != ECloseMsg));
275 Process synchronous 'control' requests. Parameters are in the first two
278 TInt DDisplayChannel::DoControl(TInt aFunction)
280 DD_TRACE(Kern::Printf(">DDisplayChannel::DoControl fn=%d\n", aFunction);)
282 TInt r = KErrNotSupported;
283 TPckgBuf<RDisplayChannel::TDisplayInfo> pkg(iChannelInfo);
286 case RDisplayChannel::ECtrlGetDisplayInfo:
287 // a1: TDisplayInfo* info [out]
288 Kern::KUDesPut(*(TDes8*)iMsg->Ptr0(), pkg); ///*&iChannelInfo*/);
292 case RDisplayChannel::ECtrlOpen:
293 // Everything is done in Construct
297 case RDisplayChannel::ECtrlClose:
302 case RDisplayChannel::ECtrlPostCompositionBuffer:
303 // a1: const TRegionFix<KMaxRectangles>* region [in]
304 // a2: TPostCount* post count [out]
305 r = PostCompositionBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1());
308 case RDisplayChannel::ECtrlPostLegacyBuffer:
309 // a1: const TRegionFix<KMaxRectangles>* region [in]
310 // a2: TPostCount* post count [out]
311 r = PostLegacyBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1());
314 case RDisplayChannel::ECtrlRegisterUserBuffer:
315 // a1: { TInt Chunk handle, TInt offset }* [in]
316 // a2: TInt* buffer ID [out]
318 __ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
320 kumemget(arg, iMsg->Ptr0(), sizeof(arg));
321 r = RegisterUserBuffer(arg[0], arg[1], (RDisplayChannel::TBufferId*)iMsg->Ptr1());
325 case RDisplayChannel::ECtrlDeregisterUserBuffer:
326 // a1: TBufferId* buffer ID [in]
327 r = DeregisterUserBuffer((RDisplayChannel::TBufferId*)iMsg->Ptr0());
330 case RDisplayChannel::ECtrlSetRotation:
331 // a1: TDisplayRotation* new rotation [in]
332 // a2: TBool* display config has changed [out]
333 r = SetRotation((RDisplayChannel::TDisplayRotation*)iMsg->Ptr0(), (TBool*)iMsg->Ptr1());
336 case RDisplayChannel::ECtrlCurrentRotation:
337 // a1: TDisplayRotation* current rotation [out]
338 r = SafePut(iMsg->Ptr0(), &iCurrentRotation, sizeof(iCurrentRotation));
345 case RDisplayChannel::ECtrlGetCompositionBufferInfo:
348 TInt index = *((TInt*)(iMsg->Ptr0()));
349 r = Kern::MakeHandleAndOpen(iMsg->Client(), iChunks[index + KFirstCompositionBuffer].iChunk);
354 SafePut(iMsg->Ptr1(),&arg,(sizeof(TInt)*2));
360 case RDisplayChannel::ECtrlVersion:
361 r = SafePut(iMsg->Ptr0(), &iVersion, sizeof(iVersion));
364 case RDisplayChannel::ECtrlNumberOfResolutions:
366 r = NumberOfResolutions();
369 case RDisplayChannel::ECtrlGetResolutions:
371 r = GetResolutions();
372 if(r == KErrCorrupt) //Resolution list changed during GetResolutions
374 r = GetResolutions();
378 case RDisplayChannel::ECtrlSetResolution:
380 r = SetResolution((TSize*)iMsg->Ptr0());
383 case RDisplayChannel::ECtrlGetResolution:
385 r = GetResolution((TSize*)iMsg->Ptr0());
388 case RDisplayChannel::ECtrlGetTwips:
390 r = GetTwips((TSize*)iMsg->Ptr0());
393 case RDisplayChannel::ECtrlNumberOfPixelFormats:
394 r = iPixelFormatArraySize;
396 case RDisplayChannel::ECtrlGetPixelFormats:
397 r = GetPixelFormats();
399 case RDisplayChannel::ECtrlSetBufferFormat:
400 r = SetBufferFormat((RDisplayChannel::TBufferFormat*)iMsg->Ptr0());
402 case RDisplayChannel::ECtrlGetBufferFormat:
403 r = SafePut(iMsg->Ptr0(), &iCurrentBufferFormat, sizeof(iCurrentBufferFormat));
405 case RDisplayChannel::ECtrlNextPlaneOffset:
406 // we support, for moment only packed pixel formats
407 r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL);
409 case RDisplayChannel::ECtrlNextLineOffset:
410 // use the internal current resolution and current rotation
411 r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL);
413 case RDisplayChannel::ECtrlNextPlaneOffsetExtended:
414 // we support, for moment only packed pixel formats
415 r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(),
416 (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1());
418 case RDisplayChannel::ECtrlNextLineOffsetExtended:
419 r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(),
420 (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1());
423 DD_TRACE(Kern::Printf("<DDisplayChannel::DoControl result=%d\n",r);)
427 TInt DDisplayChannel::GetIndexForSize(const TSize& aSize,TInt& aSpinnerOut)
429 TInt numberOfResolutions = 0;
431 TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &spinner1, iScreenNumber);
435 TPckg<TVideoInfoV01> infoPckg(info);
437 for (TInt res=0;res<numberOfResolutions;res++)
439 //pass info package to be filled in, also sending the config to read, and the screen within that
440 Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, (TAny*)&res, (TAny*)&infoPckg, iScreenNumber);
441 if (info.iSizeInPixels.iWidth==aSize.iWidth && info.iSizeInPixels.iHeight==aSize.iHeight)
443 r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &aSpinnerOut, iScreenNumber);
446 if (aSpinnerOut!=spinner1)
460 Process asynchronous requests. TRequestStatus is at iMsg->Ptr0(), and the other
461 two parameters are in iMsg->Ptr1() and iMsg->Ptr2().
463 void DDisplayChannel::DoRequest(TInt aFunction)
465 DD_TRACE(Kern::Printf(">DDisplayChannel::DoRequest fn=%d\n", aFunction);)
467 TInt r = KErrNotSupported;
471 case RDisplayChannel::EReqGetCompositionBuffer:
472 // a1: TAny** buffer address [out]
473 r = GetCompositionBuffer(static_cast<TAny**>(iMsg->Ptr1()));
476 case RDisplayChannel::EReqPostUserBuffer:
477 // a1: { TBufferId* buffer ID, const TRegionFix<KMaxRectangles>* region }* [in]
478 // a2: TPostCount* post count [out]
481 __ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
482 kumemget(arg, iMsg->Ptr1(), sizeof(arg));
483 r = PostUserBuffer(reinterpret_cast<RDisplayChannel::TBufferId*>(arg[0]), arg[1],
484 reinterpret_cast<RDisplayChannel::TPostCount*>(iMsg->Ptr2()));
488 case RDisplayChannel::EReqWaitForPost:
489 // a1: TInt* post to wait for [in]
490 r = WaitForPost(static_cast<RDisplayChannel::TPostCount*>(iMsg->Ptr1()));
493 case RDisplayChannel::EReqWaitForDisplayConnect:
494 r = WaitForDisplayConnect();
498 DD_TRACE(Kern::Printf("<DDisplayChannel::DoRequest result=%d\n",r);)
500 if (r != KRequestPending)
502 TRequestStatus* status = reinterpret_cast<TRequestStatus*>(iMsg->Ptr0());
503 Kern::RequestComplete(iMsg->Client(), status, r);
509 Process asynchronous request cancellations
511 TInt DDisplayChannel::DoCancel(TInt aRequestMask)
513 DD_TRACE(Kern::Printf(">DDisplayChannel::DoCancel mask=%x\n", aRequestMask);)
515 if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelGetCompositionBuffer))
517 if (IsCompositionBuffer(iGetBuffer))
519 iBuffer[iGetBuffer].iRequest.Complete(KErrCancel);
523 if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelPostUserBuffer))
525 if (IsUserBuffer(iPostedBuffer))
527 iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
531 if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForPost))
533 iWaitForPostRequest.Complete(KErrCancel);
535 if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForDisplayConnect))
537 iWaitForDisplayConnect.Complete(KErrCancel);
540 DD_TRACE(Kern::Printf("<DDisplayChannel::DoCancel\n",r);)
546 Get the number of resolutions on this screen
547 @return Number of resolutions if successful, otherwise a system wide error code.
549 TInt DDisplayChannel::NumberOfResolutions()
551 TInt numberOfResolutions = 0;
552 TInt error = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber);
553 if (error != KErrNone)
557 return numberOfResolutions;
562 Safely write from kernel to user memory.
563 @param aDst Pointer to destination, user memory.
564 @param aSrc Pointer to source, kernel memory.
565 @param aBytes Number of bytes to write.
566 @return KErrNone if successful, KErrArgument if either pointer is NULL.
568 TInt DDisplayChannel::SafePut(TAny* aDst, TAny* aSrc, TInt aBytes)
575 kumemput(aDst, aSrc, aBytes);
582 @param aPanic The cause of the panic.
584 void DDisplayChannel::Panic(TDisplayPanic aPanic)
586 Kern::Fault("DISPLAY", aPanic);
592 @param aPanic The cause of the panic.
594 void DDisplayChannel::ClientPanic(RDisplayChannel::TPanic aPanic)
596 _LIT(KLitDisplayChannel, "DISPLAYCHANNEL");
597 Kern::ThreadKill(iClient, EExitPanic, aPanic, KLitDisplayChannel);
602 VSync is emulated by using a nanokernel timer to call this function at the
605 void DDisplayChannel::VSyncTimerFn(TAny* aDisplayChannel)
607 reinterpret_cast<DDisplayChannel*>(aDisplayChannel)->DoVSyncTimer();
611 Instance function called on the timer thread. Queues the VSyncDfc to run on its
614 void DDisplayChannel::DoVSyncTimer(void)
617 iVSync.Again(iVSyncTicks);
622 DFC function to post the current buffer to the display.
623 @param aDisplayImpl The display object to be posted.
625 void DDisplayChannel::VSyncDfcFn(TAny* aDisplayChannel)
627 reinterpret_cast<DDisplayChannel*>(aDisplayChannel)->DoVSync();
632 Post the current buffer to the display. Signal waiting threads under various
633 conditions. This is run off the same DFC queue as message handling, so there is
634 no need to protect the fields.
636 void DDisplayChannel::DoVSync(void)
638 if(iWaitForDisplayConnect.iStatus)
641 Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, ¤tSpinner, NULL, iScreenNumber);
642 //display state changed
643 if(currentSpinner != iDisplayStateSpinner)
644 iWaitForDisplayConnect.Complete(KErrNone);
647 if (IsValidBuffer(iPostedBuffer))
649 // Complete any outstanding request for the buffer which was displayed.
650 // This either signifies the user or composition buffer becoming
652 if (iDisplayBuffer != iPostedBuffer)
654 iBuffer[iDisplayBuffer].iRequest.Complete(KErrNone);
657 iDisplayBuffer = (RDisplayChannel::TBufferId)iPostedBuffer;
658 iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet;
660 // Update the pixel pointer used when painting the client window
661 PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0,
662 (LPARAM)iBuffer[iDisplayBuffer].iAddress);
664 // check if the buffer format is modified
665 if ((iDisplayBufferFormat.iSize.iHeight != iNewBufferFormat.iSize.iHeight) ||
666 (iDisplayBufferFormat.iSize.iWidth != iNewBufferFormat.iSize.iWidth) ||
667 (iDisplayBufferFormat.iPixelFormat != iNewBufferFormat.iPixelFormat))
669 // We post in one messages everything, but we got to pack the size
670 // speculate that the maximum width and height can be represented in 16 bit
671 TUint aggregateSize = ((TUint)iNewBufferFormat.iSize.iHeight << 16) & 0xffff0000;
672 aggregateSize += (TUint)iNewBufferFormat.iSize.iWidth & 0x0000ffff;
674 WMU_SET_BUFFER_FORMAT,
676 iNewBufferFormat.iPixelFormat);
677 iDisplayBufferFormat = iNewBufferFormat;
680 if (iDisplayRotation != iNewRotation)
682 iDisplayRotation = iNewRotation;
685 switch (iDisplayRotation)
687 case RDisplayChannel::ERotation90CW:
688 flip = EEmulatorFlipLeft;
690 case RDisplayChannel::ERotation180:
691 flip = EEmulatorFlipInvert;
693 case RDisplayChannel::ERotation270CW:
694 flip = EEmulatorFlipRight;
697 flip = EEmulatorFlipRestore;
700 PostMessage(iHwnd, WM_FLIP_MESSAGE, flip, NULL);
702 iPostedRectCount = 0; // Force full invalidation
705 if (iDisplayResolution.iWidth != iNewResolution.iWidth ||
706 iDisplayResolution.iHeight != iNewResolution.iHeight)
708 iDisplayResolution = iNewResolution;
709 PostMessage(iHwnd, WMU_SET_DISPLAY_SIZE,
710 iDisplayResolution.iWidth, iDisplayResolution.iHeight);
714 // Invalidate the window contents where necessary
715 TInt count = iPostedRectCount;
718 // Order of invalidation is immaterial
721 InvalidateRect(iHwnd, &iPostedRect[count], FALSE);
724 iPostedRectCount = 0;
728 InvalidateRect(iHwnd, NULL, FALSE);
731 // Use differences to allow for wraparound
732 if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0)
734 // Post waited for is now being displayed or was dropped
735 iWaitForPostRequest.Complete(KErrNone);
737 iLastPostCount = iPostCount;
743 Set the status object for this request and the thread to complete it on, if not
745 @param aStatus The new request status.
746 @param aThread The thread on which to complete.
747 @return EFalse if the status is already set, or ETrue if the status has now been
750 TBool DDisplayChannel::TRequest::SetStatus(TThreadMessage& aMsg)
754 __ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnSet));
755 return EFalse; // In use
758 __ASSERT_DEBUG(!iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadAlreadySet));
759 DThread* thread = aMsg.Client();
760 TInt r = thread->Open();
761 __ASSERT_DEBUG( r == KErrNone, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadOpenFailed));
764 iStatus = reinterpret_cast<TRequestStatus*>(aMsg.Ptr0());
770 Complete the request with the given result. If the status has not been set, or
771 has already been completed, this does nothing.
772 @param aResult The result of the asynchronous request.
774 void DDisplayChannel::TRequest::Complete(TInt aResult)
778 __ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnComplete));
779 Kern::RequestComplete(iThread, iStatus, aResult);
780 Kern::SafeClose((DObject*&)iThread, NULL);
786 Post the current composition buffer to the display on the next frame tick.
787 @param aRegion NULL if the entire buffer has changed, or a user pointer to up
788 to TDisplayInfo::KMaxRectagles areas that have changed.
789 @param aPostCount User pointer to an integer to receive the new post count.
790 @return KErrNone, or a system-wide error code
792 TInt DDisplayChannel::PostCompositionBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
794 if (!IsCompositionBuffer(iGetBuffer))
796 return KErrNotSupported;
799 if (iWaitForPost == iPostCount)
801 // Complete wait for post (dropped)
802 iWaitForPostRequest.Complete(KErrNone);
805 if (IsUserBuffer(iPostedBuffer))
807 // Complete the user post request (not displayed)
808 iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
811 iPostedBuffer = iGetBuffer;
812 iGetBuffer = NextCompositionBuffer(iGetBuffer);
814 if (iNumCompositionBuffers > 2 && iGetBuffer == iDisplayBuffer)
816 // With more than two buffers, there must always be one available with
817 // no waiting required, so find it.
818 iGetBuffer = NextCompositionBuffer(iGetBuffer);
824 // Set iPostedRect(Count) from aRegion.
825 Panic(EDisplayPanicNotYetImplemented);
828 // What to do about wrapping?
830 iNewRotation = iCurrentRotation;
831 iNewResolution = iCurrentResolution;
832 iNewBufferFormat = iCurrentBufferFormat;
833 SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
840 Post the legacy buffer to the display on the next frame tick.
841 @param aRegion NULL if the entire buffer has changed, or a user pointer to up
842 to TDisplayInfo::KMaxRectagles areas that have changed.
843 @param aPostCount User pointer to an integer to receive the new post count.
844 @return KErrNone, or a system-wide error code
846 TInt DDisplayChannel::PostLegacyBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
848 if (iWaitForPost == iPostCount)
850 // Complete wait for post (dropped)
851 iWaitForPostRequest.Complete(KErrNone);
854 if (IsUserBuffer(iPostedBuffer))
856 iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
859 // iBuffer should NOT be NULL here!
860 __ASSERT_ALWAYS(iBuffer[KLegacyBuffer].iAddress, Panic(EDisplayPanicNoLegacyBuffer));
861 iPostedBuffer = KLegacyBuffer;
863 // Get the region into iRegion
866 // Set iPostedRect(Count) from aRegion.
867 Panic(EDisplayPanicNotYetImplemented);
871 iNewRotation = iCurrentRotation;
872 iNewResolution = iCurrentResolution;
873 iNewBufferFormat = iCurrentBufferFormat;
874 SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
881 Asynchronously request the current composition buffer. Completes immediately
882 if not already being displayed, or an error occurs.
883 @param aStatus The request status to be completed.
884 @param aAddress The user pointer to the location to put the address.
886 TInt DDisplayChannel::GetCompositionBuffer(TAny** aAddress)
888 if (!IsCompositionBuffer(iGetBuffer))
890 // No composition buffers available for use.
891 return KErrNotSupported;
894 // The address won't change, so may as well set it now.
895 TUint idx = iGetBuffer - KFirstCompositionBuffer;
896 if (SafePut(aAddress, &idx, sizeof(TUint)) != KErrNone)
901 if (iNumCompositionBuffers > 1 && iGetBuffer == iDisplayBuffer)
903 // Multi-buffer case, and buffer is currently being displayed
905 if (iBuffer[iGetBuffer].iRequest.SetStatus(*iMsg))
907 return KRequestPending;
919 Post a user buffer to the display on the next frame tick.
920 @param aBufferId The ID of the user buffer to post.
921 @param aRegion NULL if the entire buffer has changed, or a user pointer to up
922 to TDisplayInfo::KMaxRectagles areas that have changed.
923 @return KErrNone, or a system-wide error code
925 TInt DDisplayChannel::PostUserBuffer(RDisplayChannel::TBufferId* aBufferId, TAny* aRegion, RDisplayChannel::TPostCount* aPostCount)
927 RDisplayChannel::TBufferId bufferId;
928 bufferId = reinterpret_cast <RDisplayChannel::TBufferId> (aBufferId);
930 if (!IsUserBuffer(bufferId))
932 // Not a user buffer.
936 if (!iBuffer[bufferId].iChunk)
938 // User buffer not initialised.
942 if (iWaitForPost == iPostCount)
944 // Complete wait for post (dropped)
945 iWaitForPostRequest.Complete(KErrNone);
948 if (IsUserBuffer(iPostedBuffer))
950 // Complete the user post request (not displayed)
951 iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel);
954 if (bufferId == iDisplayBuffer) //pathological case
956 // Complete the current display buffer as we are superceding it with the same one
957 iBuffer[bufferId].iRequest.Complete(KErrNone);
960 // Only one buffer can be posted at any time, and if it were this user
961 // buffer, the request will have just been completed, so this shouldn't fail.
962 TBool isSet = iBuffer[bufferId].iRequest.SetStatus(*iMsg);
964 __ASSERT_DEBUG(isSet, Panic(EDisplayPanicInUse));
966 iPostedBuffer = bufferId;
971 // Set iPostedRect(Count) from aRegion.
972 Panic(EDisplayPanicNotYetImplemented);
976 iNewRotation = iCurrentRotation;
977 iNewResolution = iCurrentResolution;
978 iNewBufferFormat = iCurrentBufferFormat;
979 SafePut(aPostCount, &iPostCount, sizeof(iPostCount));
981 return KRequestPending;
985 Asynchronous request notification when the given post count is reached (or
987 @param aStatus The request status to be completed.
988 @param aPostCount The count to wait for.
990 TInt DDisplayChannel::WaitForPost(RDisplayChannel::TPostCount* aPostCount)
994 kumemget(&postCount, aPostCount, sizeof(RDisplayChannel::TPostCount));
996 if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0)
998 // Set up the request to be completed when the post occurs
999 if (iWaitForPostRequest.SetStatus(*iMsg))
1001 iWaitForPost = postCount;
1002 return KRequestPending;
1005 // Already waiting for a post
1009 // Requested post already displayed/dropped
1014 Asynchronous request notification when the display connection state changes.
1015 This occurs when the display is disconnected, connected with no list, or a list of modes becomes available or is updated.
1017 TInt DDisplayChannel::WaitForDisplayConnect()
1020 Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &iDisplayStateSpinner, NULL, iScreenNumber);
1022 if (iWaitForDisplayConnect.SetStatus(*iMsg))
1024 return KRequestPending;
1027 // Already waiting for a post
1033 Set the rotation of the screen on the next frame. If the buffer contents will
1034 not be valid, the flag set. The validity of the buffer is down to whether the
1035 width and height change.
1037 @param aNewRotation Address in user space of the new rotation setting.
1038 @param aDisplayConfigChanged Address in user space of where to put whether the
1039 orientation specific info to use has changed following the rotation setting.
1040 @return KErrNone, or KErrArgument if an argument was invalid.
1042 TInt DDisplayChannel::SetRotation(RDisplayChannel::TDisplayRotation* aNewRotation,
1043 TBool* aDisplayConfigChanged)
1045 RDisplayChannel::TDisplayRotation newRotation;
1047 __ASSERT_DEBUG(aNewRotation, Panic(EDisplayPanicNullArgument));
1049 kumemget(&newRotation, aNewRotation, sizeof(newRotation));
1051 if (((TInt)newRotation - 1) & newRotation)
1053 // More than one bit is set, which is not valid
1054 return KErrArgument;
1057 if ((iChannelInfo.iAvailableRotations & newRotation) == 0)
1059 // Rotation is not supported
1060 return KErrArgument;
1063 TBool displayConfigChanged = (IsFlipped(newRotation) != IsFlipped(iCurrentRotation));
1064 iCurrentRotation = newRotation;
1066 SafePut(aDisplayConfigChanged, &displayConfigChanged, sizeof(TBool));
1073 Register a user buffer. Assign an ID for it (if available) and open the chunk to
1075 @param aChunkHandle The chunk handle.
1076 @param aOffset The offset from the chunk base address to the start of the
1078 @param aBufferId The address in user space of where to put the buffer ID.
1080 TInt DDisplayChannel::RegisterUserBuffer(TInt aChunkHandle, TInt aOffset,
1081 RDisplayChannel::TBufferId* aBufferId)
1085 return KErrArgument;
1088 NKern::ThreadEnterCS();
1089 DChunk* chunk = Kern::OpenSharedChunk(iMsg->Client(), aChunkHandle,
1091 NKern::ThreadLeaveCS();
1094 return KErrBadHandle;
1097 TLinAddr kernelAddress;
1099 const TInt bufferSize = (iDisplayResolution.iWidth * iDisplayResolution.iHeight);
1100 TInt r = Kern::ChunkAddress(chunk,aOffset,bufferSize,kernelAddress);
1103 NKern::ThreadEnterCS();
1104 Kern::ChunkClose(chunk);
1105 NKern::ThreadLeaveCS();
1109 // Search for an empty slot
1110 for (TInt index = KFirstUserBuffer; index < (KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers); index++)
1112 if (!iBuffer[index].iChunk)
1114 // Found one, so fill in the details and return the index as the ID.
1115 iBuffer[index].iChunk = chunk;
1116 iBuffer[index].iAddress = (TAny*)(kernelAddress);
1117 kumemput(aBufferId, &index, sizeof(RDisplayChannel::TBufferId));
1122 // No slots available.
1123 NKern::ThreadEnterCS();
1124 Kern::ChunkClose(chunk);
1125 NKern::ThreadLeaveCS();
1131 Deregister a user buffer.
1132 @param aBufferId The buffer ID.
1134 TInt DDisplayChannel::DeregisterUserBuffer(RDisplayChannel::TBufferId* aBufferId)
1136 RDisplayChannel::TBufferId bufferId;
1138 __ASSERT_DEBUG(aBufferId, Panic(EDisplayPanicNullArgument));
1139 kumemget(&bufferId, aBufferId, sizeof(RDisplayChannel::TBufferId));
1141 if (!IsUserBuffer(bufferId))
1144 return KErrArgument;
1147 TBufferInfo* buffer = &iBuffer[bufferId];
1148 if (!buffer->iChunk)
1151 return KErrArgument;
1154 if (iDisplayBuffer == bufferId)
1159 if (iPostedBuffer == bufferId)
1161 // Was queued to be posted
1162 iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet;
1163 iPostedRectCount = 0;
1166 // Cancel any outstanding request on the buffer and clear out the fields.
1167 buffer->iRequest.Complete(KErrCancel);
1168 NKern::ThreadEnterCS();
1169 Kern::ChunkClose(buffer->iChunk);
1170 NKern::ThreadLeaveCS();
1171 buffer->iChunk = NULL;
1172 buffer->iAddress = NULL;
1178 Get all resolutions available for this screen and insert to a descriptor
1179 @return KErrNone if successful, otherwise a system wide error code.
1181 TInt DDisplayChannel::GetResolutions()
1184 __ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
1185 __ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
1186 //get the number of resolutions (as above)
1187 TInt numberOfResolutions = 0;
1188 TInt refStateSpinner, curStateSpinner;
1189 //Get the number of resolutions as well as the display state spinner at this point
1190 r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &refStateSpinner, iScreenNumber);
1198 Kern::KUDesInfo(*(const TDesC*)iMsg->Ptr0(),length,maxLength);
1200 if ((maxLength/static_cast<TInt>(sizeof(RDisplayChannel::TResolution))) < numberOfResolutions)
1202 return KErrOverflow;
1206 TPckg<TVideoInfoV01> infoPckg(info);
1207 RDisplayChannel::TResolution resolution = {{0,0},{0,0},RDisplayChannel::ERotationAll};
1208 TPtr8 tempDes(NULL,0);
1211 for (i=0;i<numberOfResolutions;i++)
1213 //before filling the package, the display state needs to be checked for consistency
1214 Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &curStateSpinner, NULL, iScreenNumber);
1216 if(curStateSpinner != refStateSpinner)
1217 { //display state has changed, the resolution list we trying to get becomes corrupted
1218 Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
1222 //pass info package to be filled in, also sending the config to read, and the screen within that
1223 Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber);
1225 resolution.iPixelSize = info.iSizeInPixels;
1226 resolution.iTwipsSize = info.iSizeInTwips;
1228 tempDes.Set((TUint8*)&resolution,sizeof(RDisplayChannel::TResolution),sizeof(RDisplayChannel::TResolution));
1229 r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(),tempDes,i*sizeof(RDisplayChannel::TResolution),iMsg->Client());
1233 Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
1237 Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution));
1238 SafePut(iMsg->Ptr1(), &numberOfResolutions, sizeof(numberOfResolutions));
1244 TInt DDisplayChannel::SetResolution(TSize* aSize)
1248 ClientPanic(RDisplayChannel::ENullArgument);
1249 return KErrArgument;
1253 kumemget32(&size, aSize, sizeof(size));
1254 if (size.iWidth < 0 || size.iHeight < 0)
1256 ClientPanic(RDisplayChannel::EInvalidResolution);
1257 return KErrArgument;
1260 if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,
1261 __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
1263 return KErrPermissionDenied;
1266 // Validate size. Return KErrArgument on failure.
1267 //Get the number of resolutions
1268 TInt numberOfResolutions;
1269 TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber);
1275 TPckg<TVideoInfoV01> infoPckg(info);
1276 for (TInt i = 0; i < numberOfResolutions; i++)
1278 //pass info package to be filled in, also sending the config to read, and the screen within that
1279 Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber);
1281 if (info.iSizeInPixels.iWidth == size.iWidth &&
1282 info.iSizeInPixels.iHeight == size.iHeight)
1283 { //matched resolution
1284 iCurrentResolution = size;
1285 iCurrentTwips = info.iSizeInTwips;
1287 if (iCurrentResolution.iHeight > iNewBufferFormat.iSize.iHeight ||
1288 iCurrentResolution.iWidth > iNewBufferFormat.iSize.iWidth)
1290 // going back to initial settings and, we hope,
1291 // the buffers could still be displayed correctly, but we have no guarantee
1292 iCurrentBufferFormat = iInitialBufferFormat;
1297 return KErrArgument; //if reached here, it did not match aSize to any config resolution
1300 TInt DDisplayChannel::GetResolution(TSize* aSize)
1302 TInt numberOfResolutions;
1303 TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions,
1304 &numberOfResolutions, NULL, iScreenNumber);
1308 if (numberOfResolutions > 0)
1310 SafePut(aSize, &iCurrentResolution, sizeof(iCurrentResolution));
1314 TSize resolution = {0,0};
1315 SafePut(aSize, &resolution, sizeof(resolution));
1321 TInt DDisplayChannel::GetTwips(TSize* aSize)
1323 TInt numberOfResolutions;
1324 TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions,
1325 &numberOfResolutions, NULL, iScreenNumber);
1329 if (numberOfResolutions > 0)
1331 SafePut(aSize, &iCurrentTwips, sizeof(iCurrentTwips));
1335 TSize twips = {0,0};
1336 SafePut(aSize, &twips, sizeof(twips));
1342 Get all the pixel formats available and insert them to a descriptor
1343 @return KErrNone if successful, otherwise a system wide error code.
1345 TInt DDisplayChannel::GetPixelFormats()
1348 __ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument));
1349 __ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument));
1350 //get the number of resolutions (as above)
1351 TPtr8 pixelFormatDes(NULL,0);
1352 TInt length = ((TInt)sizeof(RDisplayChannel::TPixelFormat)) * iPixelFormatArraySize;
1353 pixelFormatDes.Set((TUint8*)iPixelFormatArray, length, length);
1354 r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(), pixelFormatDes, 0, iMsg->Client());
1357 Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(), length);
1358 SafePut(iMsg->Ptr1(), &iPixelFormatArraySize, sizeof(iPixelFormatArraySize));
1364 TInt DDisplayChannel::SetBufferFormat(RDisplayChannel::TBufferFormat* aBufferFormat)
1368 ClientPanic(RDisplayChannel::ENullArgument);
1369 return KErrArgument;
1372 if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,
1373 __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
1375 return KErrPermissionDenied;
1378 RDisplayChannel::TBufferFormat bufferFormat;
1379 kumemget32(&bufferFormat, aBufferFormat, sizeof(RDisplayChannel::TBufferFormat));
1382 if (iCurrentResolution.iHeight > bufferFormat.iSize.iHeight ||
1383 iCurrentResolution.iWidth > bufferFormat.iSize.iWidth ||
1384 bufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth ||
1385 bufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth)
1387 //return error on failure
1388 return KErrArgument;
1391 // check we received one of the supported formats.
1392 for (TInt i = 0; i < iPixelFormatArraySize; i++)
1394 if (bufferFormat.iPixelFormat == iPixelFormatArray[i])
1396 // the arguments are all validated at this point, update the current format
1397 iCurrentBufferFormat = bufferFormat;
1402 //return error on failure
1403 return KErrArgument;
1406 TInt DDisplayChannel::ValidateBufferFormat(const RDisplayChannel::TBufferFormat& aBufferFormat,
1407 const RDisplayChannel::TResolution& aResolution)
1409 // Validate the size reported in buffer format against the given resolution
1410 if (aResolution.iPixelSize.iHeight > aBufferFormat.iSize.iHeight ||
1411 aResolution.iPixelSize.iWidth > aBufferFormat.iSize.iWidth ||
1412 aBufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth ||
1413 aBufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth)
1415 //return error on failure
1416 return KErrArgument;
1419 // check we received one of the supported formats.
1420 for (TInt i = 0; i < iPixelFormatArraySize; i++)
1422 if (aBufferFormat.iPixelFormat == iPixelFormatArray[i])
1428 return KErrArgument;
1431 TInt DDisplayChannel::NextPlaneOffset(RDisplayChannel::TBufferFormat* aBufferFormat,
1432 RDisplayChannel::TBufferFormatContext* aContext)
1436 ClientPanic(RDisplayChannel::ENullArgument);
1437 return KErrArgument;
1440 if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,
1441 __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
1443 return KErrPermissionDenied;
1446 RDisplayChannel::TBufferFormat bufferFormat;
1447 kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat));
1449 RDisplayChannel::TResolution resolution;
1450 RDisplayChannel::TDisplayRotation rotation;
1454 RDisplayChannel::TBufferFormatContext context;
1455 kumemget32(&context, aContext, sizeof(context));
1456 resolution = context.iResolution;
1457 rotation = context.iRotation;
1461 resolution.iPixelSize = iCurrentResolution;
1462 rotation = iCurrentRotation;
1465 TInt err = ValidateBufferFormat(bufferFormat, resolution);
1467 if (err != KErrNone)
1471 //it assumes no planar pixel formats are supported by this driver implementation
1475 TInt DDisplayChannel::NextLineOffset(RDisplayChannel::TBufferFormat* aBufferFormat,
1476 RDisplayChannel::TBufferFormatContext* aContext)
1480 ClientPanic(RDisplayChannel::ENullArgument);
1481 return KErrArgument;
1484 if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,
1485 __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)")))
1487 return KErrPermissionDenied;
1490 RDisplayChannel::TBufferFormat bufferFormat;
1491 kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat));
1493 RDisplayChannel::TResolution resolution;
1494 RDisplayChannel::TDisplayRotation rotation;
1498 RDisplayChannel::TBufferFormatContext context;
1499 kumemget32(&context, aContext, sizeof(context));
1500 resolution = context.iResolution;
1501 rotation = context.iRotation;
1505 resolution.iPixelSize = iCurrentResolution;
1506 rotation = iCurrentRotation;
1509 TInt err = ValidateBufferFormat(bufferFormat, resolution);
1511 if (err != KErrNone)
1517 //validating the pixel format and getting the pixel size in bits
1518 switch (bufferFormat.iPixelFormat)
1520 case EUidPixelFormatXRGB_4444: // RGB4444
1521 case EUidPixelFormatARGB_4444:
1522 case EUidPixelFormatRGB_565: // RGB565
1525 case EUidPixelFormatXRGB_8888: // Really 32bpp, but top 8 unused
1526 case EUidPixelFormatARGB_8888:
1527 case EUidPixelFormatARGB_8888_PRE:
1531 // We got an error, it seems. The pixel format is not supported
1532 // Let's panic because the pixel format has just been validated
1533 Panic(EDisplayPanicInvalidBitDepth);
1537 TInt widthInPixel = 0; // pixels
1539 // let's take in consideration the given rotation
1542 case RDisplayChannel::ERotation90CW:
1543 case RDisplayChannel::ERotation270CW:
1544 widthInPixel = bufferFormat.iSize.iHeight;
1547 widthInPixel = bufferFormat.iSize.iWidth;
1551 // we have to round up to 32 bits word. This is a Ms Windows limitation
1552 TInt stride = _ALIGN_UP((widthInPixel * bpp), 32) >> 3;