Update contrib.
1 // Copyright (c) 2006-2010 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.
14 // This module implements the functions that create the screen class depending
15 // on the screen type.
23 /********************************************************************/
26 #include "ScreenInfo.h"
29 #include <graphics/gdi/gdiconsts.h>
30 #include <graphics/suerror.h>
32 Creates an instance of CFbsDrawDevice class.
33 @param aScreenNo Screen number
34 @param aDispMode Display mode
35 @param aScreenInfo Screen parameters: video memory address and screen size
36 @return A pointer to the created CFbsDrawDevice object
37 @leave System-wide error code including KErrNoMemory
40 static CFbsDrawDevice* CreateInstanceL(TInt aScreenNo,
41 TDisplayMode aDispMode,
42 const TScreenInfo& aScreenInfo)
44 CFbsDrawDevice* drawDevice = NULL;
48 //there is some "ambiguity" about 24 and 32 bit modes...
49 //They are both byte per color component, and both actually have 32 bits per pixel memory use.
50 //This ambiguity does not exist between 12 and 16 bit modes,
51 //because they are distinct color component patterns (x444, 565)
52 //but for now 24 and 32 bit modes are considered equivalent here.
54 if (HAL::Get(aScreenNo, HALData::EDisplayNumModes,modeCount)== KErrNone && modeCount>=1)
55 { //If multiple modes are supported then the highest bpp must be found
57 TInt reqBpp= TDisplayModeUtils::NumDisplayModeBitsPerPixel(aDispMode);
59 if ( reqBpp==24 || reqBpp==32 ) //Best to be specific here. Who knows how likely is 30 or 64 bpp support?
61 reqBpp2=32+24 - reqBpp; //reflect 24<==>32
62 //Important compile-time decision embedded here: Only one 32-bit mode is supported
63 if(CFbsDrawDevice::DisplayMode16M() != aDispMode)
65 User::Leave(KErrNotSupported);
68 for (TInt mode=0; mode<modeCount; mode++)
71 if(HAL::Get(aScreenNo, HALData::EDisplayBitsPerPixel, modeBpp) == KErrNone)
73 if (modeBpp==reqBpp || modeBpp==reqBpp2)
82 { //This is the expected error code
83 User::Leave(KErrNotSupported);
85 //Switch the display mode, call the constructor of the class defined
88 /** Monochrome display mode (1 bpp) */
91 CDrawOneBppScreenBitmap* drawDeviceX = new (ELeave) CDrawOneBppScreenBitmap;
92 drawDevice=drawDeviceX;
93 CleanupStack::PushL(drawDevice) ;
94 User::LeaveIfError(drawDeviceX->ConstructScreen(
97 aScreenInfo.iSize,matchedMode));
100 /** Four grayscales display mode (2 bpp) */
103 CDrawTwoBppScreenBitmap* drawDeviceX = new (ELeave) CDrawTwoBppScreenBitmap;
104 drawDevice=drawDeviceX;
105 CleanupStack::PushL(drawDevice) ;
106 User::LeaveIfError(drawDeviceX->ConstructScreen(
108 aScreenInfo.iAddress,
109 aScreenInfo.iSize,matchedMode));
112 /** 16 grayscales display mode (4 bpp) */
115 CDrawFourBppScreenBitmapGray* drawDeviceX = new (ELeave) CDrawFourBppScreenBitmapGray;
116 drawDevice=drawDeviceX;
117 CleanupStack::PushL(drawDevice) ;
118 User::LeaveIfError(drawDeviceX->ConstructScreen(
120 aScreenInfo.iAddress,
121 aScreenInfo.iSize,matchedMode));
124 /** 256 grayscales display mode (8 bpp) */
127 CDrawEightBppScreenBitmapGray* drawDeviceX = new (ELeave) CDrawEightBppScreenBitmapGray;
128 drawDevice=drawDeviceX;
129 CleanupStack::PushL(drawDevice) ;
130 User::LeaveIfError(drawDeviceX->ConstructScreen(
132 aScreenInfo.iAddress,
133 aScreenInfo.iSize,matchedMode));
136 /** Low colour EGA 16 colour display mode (4 bpp) */
139 CDrawFourBppScreenBitmapColor* drawDeviceX = new (ELeave) CDrawFourBppScreenBitmapColor;
140 drawDevice=drawDeviceX;
141 CleanupStack::PushL(drawDevice) ;
142 User::LeaveIfError(drawDeviceX->ConstructScreen(
144 aScreenInfo.iAddress,
145 aScreenInfo.iSize,matchedMode));
148 /** 256 colour display mode (8 bpp) */
151 CDrawEightBppScreenBitmapColor* drawDeviceX = new (ELeave) CDrawEightBppScreenBitmapColor;
152 drawDevice=drawDeviceX;
153 CleanupStack::PushL(drawDevice) ;
154 User::LeaveIfError(drawDeviceX->ConstructScreen(
156 aScreenInfo.iAddress,
157 aScreenInfo.iSize,matchedMode));
160 /** 4,000 colour display mode (16 bpp) */
161 case EColor4K: // 12 Bpp color mode
163 CDrawTwelveBppScreenBitmapColor* drawDeviceX = new (ELeave) CDrawTwelveBppScreenBitmapColor;
164 drawDevice=drawDeviceX;
165 CleanupStack::PushL(drawDevice) ;
166 User::LeaveIfError(drawDeviceX->ConstructScreen(
168 aScreenInfo.iAddress,
169 aScreenInfo.iSize,matchedMode));
173 case EColor64K: // 16 Bpp color mode
175 CDrawSixteenBppScreenBitmap* drawDeviceX = new (ELeave) CDrawSixteenBppScreenBitmap;
176 drawDevice=drawDeviceX;
177 CleanupStack::PushL(drawDevice) ;
178 User::LeaveIfError(drawDeviceX->ConstructScreen(
180 aScreenInfo.iAddress,
181 aScreenInfo.iSize,matchedMode));
186 CDrawUTwentyFourBppScreenBitmap* drawDeviceX = new (ELeave) CDrawUTwentyFourBppScreenBitmap;
187 drawDevice=drawDeviceX;
188 CleanupStack::PushL(drawDevice) ;
189 User::LeaveIfError(drawDeviceX->ConstructScreen(
191 aScreenInfo.iAddress,
192 aScreenInfo.iSize,matchedMode));
197 CDrawThirtyTwoBppScreenBitmapAlpha* drawDeviceX = new (ELeave) CDrawThirtyTwoBppScreenBitmapAlpha;
198 drawDevice=drawDeviceX;
199 CleanupStack::PushL(drawDevice) ;
200 User::LeaveIfError(drawDeviceX->ConstructScreen(
202 aScreenInfo.iAddress,
203 aScreenInfo.iSize,matchedMode));
208 CDrawThirtyTwoBppScreenBitmapAlphaPM* drawDeviceX = new (ELeave) CDrawThirtyTwoBppScreenBitmapAlphaPM;
209 drawDevice=drawDeviceX;
210 CleanupStack::PushL(drawDevice) ;
211 User::LeaveIfError(drawDeviceX->ConstructScreen(
213 aScreenInfo.iAddress,
214 aScreenInfo.iSize,matchedMode));
218 User::Leave(KErrNotSupported);
221 CleanupStack::Pop(drawDevice);
226 /********************************************************************/
227 /* Implementation of CFbsDrawDevice class */
228 /********************************************************************/
231 This function calls the correct constructor in function of the display mode.
232 @param aInfo, Structure of the LCD info
233 @param aDispMode, display mode
234 @return A pointer to just created screen device, which implements CFbsDrawDevice interface
235 @deprecated Use CFbsDrawDevice::NewScreenDeviceL(TInt aScreenNo, TDisplayMode aDispMode)
237 EXPORT_C CFbsDrawDevice* CFbsDrawDevice::NewScreenDeviceL(TScreenInfoV01 aInfo, TDisplayMode aDispMode)
239 __ASSERT_ALWAYS(aInfo.iScreenAddressValid, Panic(EScreenDriverPanicInvalidWindowHandle));
240 TScreenInfo screenInfo(aInfo.iScreenAddress, aInfo.iScreenSize);
241 return ::CreateInstanceL(KDefaultScreenNo, aDispMode, screenInfo);
247 Creates a new screen device instance, which implements CFbsDrawDevice interface.
248 The method has to be implemented for each type of supported video hardware.
249 @param aScreenNo Screen number
250 @param aDispMode Requested display mode
251 @return A pointer to just created screen device, which implements CFbsDrawDevice interface
252 @leave KErrNoMemory Not enough memory
253 KErrNotSupported The requested screen device type is not supported
255 EXPORT_C CFbsDrawDevice* CFbsDrawDevice::NewScreenDeviceL(TInt aScreenNo,
256 TDisplayMode aDispMode)
258 TInt width = 0, height = 0;
259 User::LeaveIfError(HAL::Get(aScreenNo, HALData::EDisplayXPixels, width));
260 User::LeaveIfError(HAL::Get(aScreenNo, HALData::EDisplayYPixels, height));
261 __ASSERT_ALWAYS(width > 0 && height > 0, Panic(EScreenDriverPanicInvalidHalValue));
265 TScreenInfo screenInfo(address, TSize(width, height));
266 return ::CreateInstanceL(aScreenNo, aDispMode, screenInfo);
270 Depending on the current graphics hardware this
271 will return one of the 16M video modes defined in
272 TDisplayMode, or ENone if a 16M video mode is not supported.
273 The method has to be implemented on all hardware platforms.
274 @return a 16M display mode or ENone.
275 ENone - it means that current hardware doesn't have 16M color mode.
277 EXPORT_C TDisplayMode CFbsDrawDevice::DisplayMode16M()
284 Complete construction of the helper object.
285 @param aScreenNo The screen number, starting from 0.
286 @param aPixelFormat Pixel format UID or 0 for default based on bpp
287 @return KErrNone or a system wide error value.
289 TInt CScreenDeviceHelper::Construct(TInt aScreenNo, TUidPixelFormat aPixelFormat, TUint aHalMode)
291 iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EScreenField] = aScreenNo; // Screen number
292 iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField] = aHalMode; // Rotation and hal mode index
293 iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::ETypeGuidField] = aPixelFormat; //May be zero for non-GCE modes
294 iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::ETypeClassField]
295 = ((TUint32)(TSurfaceId::EScreenSurface) << TSurfaceId::TScreenSurfaceUsage::ETypeClassShift); // Type
296 iAssignedOrientation = EDeviceOrientationNormal; // Actual rotation is held seperately from surface ID
300 TInt ret = HAL::Get(aScreenNo,HALData::EDisplayMemoryHandle,val);
303 __ASSERT_DEBUG(val != 0, Panic(EScreenDriverPanicInvalidHalValue));
305 ret = chunk.SetReturnedHandle(val);
311 ret = iChunk.Duplicate(RThread(), EOwnerProcess);
312 // Close before checking for errors, as we don't want to leave the
313 // temporary chunk handle floating about.
321 // KErrNotSupported is returned if we can't get the Handle because it's not a driver
322 // that supports the concept. We don't return that error, since it's perfectly valid
323 // to not support this.
324 else if (ret != KErrNotSupported)
328 return iSurfaceUpdateSession.Connect();
331 CScreenDeviceHelper::~CScreenDeviceHelper()
334 iSurfaceUpdateSession.Close();
338 void CScreenDeviceHelper::NotifyWhenAvailable(TRequestStatus& aStatus)
340 iSurfaceUpdateSession.NotifyWhenAvailable(aStatus);
343 void CScreenDeviceHelper::CancelUpdateNotification()
345 iSurfaceUpdateSession.CancelAllUpdateNotifications();
349 Implementation of corresponding function in CDrawDevice, utilizing a tracked
350 update region. Updates the screen from the surface, if the update region is
353 void CScreenDeviceHelper::Update()
355 TRequestStatus updateComplete = KRequestPending;
356 Update(updateComplete);
357 User::WaitForRequest(updateComplete);
360 void CScreenDeviceHelper::Update(TRequestStatus& aStatus)
362 if (!iUpdateRegion.IsEmpty())
364 iSurfaceUpdateSession.NotifyWhenAvailable(aStatus);
365 iSurfaceUpdateSession.SubmitUpdate(KAllScreens, iSurface, 0, &iUpdateRegion);
366 iUpdateRegion.Clear();
370 TRequestStatus* pComplete=&aStatus;
371 User::RequestComplete(pComplete,KErrNone);
377 Implementation of corresponding function in CDrawDevice, utilizing a tracked
378 update region. Adds the given rectangle to the update region.
379 @param aRect Rectangle to be added to the update region.
381 void CScreenDeviceHelper::UpdateRegion(const TRect& aRect)
385 // Adding an empty rectangle should have no effect.
389 if (iUpdateRegion.CheckError())
391 // Try to ensure the region doesn't keep an error forever.
392 iUpdateRegion.Clear();
395 TRect bounds(iUpdateRegion.BoundingRect());
396 iUpdateRegion.AddRect(aRect);
398 // If the region fills up, start again with the old bounding box plus this
400 if (iUpdateRegion.CheckError())
402 iUpdateRegion.Clear();
403 iUpdateRegion.AddRect(bounds);
404 iUpdateRegion.AddRect(aRect);
409 Reset the update region to be empty without submitting any outstanding updates.
411 void CScreenDeviceHelper::ResetUpdateRegion()
413 iUpdateRegion.Clear();
417 This function returns the current surface in use for this screen.
418 @param aSurface The identifier to be updated with the current screen surface.
420 void CScreenDeviceHelper::GetSurface(TSurfaceId& aSid) const
426 This function is used to request the device orientations supported by the
428 @return A bitwise combination of one or more TDeviceOrientation enumerated
429 values indicating the device orientations that are supported by this device.
431 TUint CScreenDeviceHelper::DeviceOrientationsAvailable(const TSize& aScreenSize) const
433 //All that can be reported here is what the CScreenDevice can support via HAL
434 //With generic driver, the runtime can be further restricted by the GCE
435 if ( aScreenSize.iWidth && aScreenSize.iWidth==aScreenSize.iHeight )
437 return EDeviceOrientationNormal | EDeviceOrientation90CW |
438 EDeviceOrientation180 | EDeviceOrientation270CW;
440 //Query base HAL for rotated view support
441 TInt offset1=iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField]|TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag;
442 if ( HAL::Get(ScreenNumber(), HALData::EDisplayOffsetBetweenLines, offset1)==KErrNone
445 return EDeviceOrientationNormal | EDeviceOrientation90CW |
446 EDeviceOrientation180 | EDeviceOrientation270CW;
449 return EDeviceOrientationNormal | EDeviceOrientation180;
453 This function selects the surface and device buffer to use in the screen
454 driver for this screen. Normal and 180° rotations will generally use the same
455 surface, while 90° and 270° will use another. The surfaces may have different
456 width, height, stride and surface ID, so functions that make use of any of
457 these may be affected after a change in surface orientation, and the return
458 value should be checked for this reason.
460 This call does not change the way rendering is performed, but may operate on
461 the underlying memory using a new shape. The call does not change the display
462 controller's settings, as this is handled via the GCE. All this changes are the
463 internal attributes of the screen device and driver objects. A CFbsBitGc object
464 activated on the device should be reactivated, to update its own attributes, or
465 drawing may be corrupted.
467 Note: while TDeviceOrientation values do not directly correspond to
468 CFbsBitGc::TGraphicsOrientation values, and cannot be used interchangeably, it
469 is simple to generate the former from the latter using the left-shift operator
470 (i.e. device == (1 << graphics)). In particular a device orientation of
471 90 degrees clockwise is equivalent to a content orientation of 90 degrees anti-
472 clockwise, which is what TGraphicsOrientation refers to for the equivalent
473 setting. The letters "CW" in the TDeviceOrientation enumeration refer
474 to a clockwise device rotation, so EDeviceOrientation90CW is a 90 degree
475 clockwise rotation of the device.
477 @param aOrientation The new device orientation, relative to the normal physical
479 @param aNewSize The new pixel dimensions of the surface to be used.
480 @return ETrue is returned if any of the surface, width, height or stride
481 attributes of the screen device have changed as a result of the call or EFalse
482 if none of the attributes have changed.
484 TBool CScreenDeviceHelper::SetDeviceOrientation(TDeviceOrientation aOrientation, TSize& aNewSize)
486 // Check only one orientation bit is set
487 if (((TInt)aOrientation - 1) & aOrientation)
489 Panic(EScreenDriverPanicInvalidParameter);
492 // Check the orientation is supported
493 if ((DeviceOrientationsAvailable(aNewSize) & aOrientation) == 0)
495 Panic(EScreenDriverPanicInvalidParameter);
498 iAssignedOrientation=aOrientation;
500 return SetDeviceFlipMode(ConvertFlip(aOrientation),aNewSize);
502 /** Sets or clears the flipped flag indicating that the width and height have been swapped for a +/-90 deg rotation
503 * Rotation is not required for square displays unless the Hal wants one.
505 TBool CScreenDeviceHelper::SetDeviceFlipMode(TBool aFlip, TSize& aNewSize)
507 //This is now a private method that doesn't validate aFlip
508 TInt newFlipMode= iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
511 newFlipMode|=TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag;
515 newFlipMode&=~TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag;
517 if (newFlipMode == iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField])
519 // No change to mode requested.
523 err|=HAL::Get(ScreenNumber(), HALData::EDisplayXPixels, aNewSize.iWidth);
524 err|=HAL::Get(ScreenNumber(), HALData::EDisplayYPixels, aNewSize.iHeight);
525 __ASSERT_ALWAYS(err==KErrNone,Panic(EScreenDriverPanicInvalidHalValue));
526 if (aNewSize.iWidth==aNewSize.iHeight)
527 { //Attempt optimisation to not flip if the screen is square, so avoid recomposition.
528 TInt stride1=iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
529 TInt stride2=stride1^TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag;
530 TInt offset1=stride1;
531 TInt offset2=stride2;
532 //Does the rotated mode have any other attributes that differ?
533 //It is just about possible to imagine that the rotated display
534 //wants to use a different setting for the flipped legacy buffer for optimisation purposes.
535 err|=HAL::Get(ScreenNumber(), HALData::EDisplayOffsetToFirstPixel, offset1);
536 err|=HAL::Get(ScreenNumber(), HALData::EDisplayOffsetBetweenLines, stride1);
537 //The existing mode settings should not fail... we are already in this mode!
538 __ASSERT_ALWAYS(err==KErrNone,Panic(EScreenDriverPanicInvalidHalValue));
540 TInt rotatedErr = HAL::Get(ScreenNumber(), HALData::EDisplayOffsetToFirstPixel, offset2);
541 rotatedErr |= HAL::Get(ScreenNumber(), HALData::EDisplayOffsetBetweenLines, stride2);
542 //The HAL may indicate rotation is not required by failing to return data or returning the same data
543 if ( rotatedErr!=KErrNone || stride2==0 ) //Offset can legitimately be zero.
545 // No change to mode supported.
548 if ( stride1==stride2 && offset1==offset2 )
550 // No change to mode needed.
555 iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField] = newFlipMode;
558 // Swap width and height in the alternate orientation.
559 aNewSize.SetSize(aNewSize.iHeight, aNewSize.iWidth);
563 /** Returns the stride for the given mode.
564 * This method must not panic if it should fail!
566 TUint CScreenDeviceHelper::BytesPerScanline() const
568 TInt linepitchInBytes = iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
569 TInt ret = HAL::Get(ScreenNumber(),HALData::EDisplayOffsetBetweenLines,linepitchInBytes);
574 return linepitchInBytes ;
576 /** Returns the address for the image data
577 * This method must not panic if it should fail!
579 void* CScreenDeviceHelper::AddressFirstPixel() const
581 TInt bufferStartAddress = iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
585 // The "chunk" way to do this is to get the handle of the chunk, and then the base address of the
587 bufferStartAddress = (TInt)iChunk.Base();
591 // Chunk not supported, use older HAL call to get the buffer address.
592 ret = HAL::Get(ScreenNumber(),HALData::EDisplayMemoryAddress,bufferStartAddress);
598 TInt bufferOffsetFirstPixel = iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField];
599 ret = HAL::Get(ScreenNumber(),HALData::EDisplayOffsetToFirstPixel,bufferOffsetFirstPixel);
604 return (void*)(bufferStartAddress+bufferOffsetFirstPixel);
608 Returns the current device width/height flip state of this surface, representing a +/-90 deg rotation.
610 TBool CScreenDeviceHelper::DeviceFlipped() const
612 return (iSurface.iInternal[TSurfaceId::TScreenSurfaceUsage::EHalField] & TSurfaceId::TScreenSurfaceUsage::EHalFlippedFlag) != 0; //!=0 forces true --> 1
617 Returns the current device orientation.
619 TDeviceOrientation CScreenDeviceHelper::DeviceOrientation() const
621 return iAssignedOrientation;
623 /** Returns an accurate scaling factor between twips and pixels in width.
626 TInt CScreenDeviceHelper::HorzTwipsPerThousandPixels(const TSize& aPixels)const
628 __ASSERT_DEBUG(aPixels.iWidth, Panic(EScreenDriverPanicInvalidSize));
631 TInt r = HAL::Get(ScreenNumber(), SecondIfFlipped(HAL::EDisplayXTwips,HAL::EDisplayYTwips), width);
632 __ASSERT_DEBUG(r==KErrNone && width!=0, Panic(EScreenDriverPanicInvalidHalValue));
634 return (width * 1000) / aPixels.iWidth;
636 /** Returns an accurate scaling factor between twips and pixels in height.
638 TInt CScreenDeviceHelper::VertTwipsPerThousandPixels(const TSize& aPixels)const
640 __ASSERT_DEBUG(aPixels.iHeight, Panic(EScreenDriverPanicInvalidSize));
643 TInt r = HAL::Get(ScreenNumber(), SecondIfFlipped(HAL::EDisplayYTwips,HAL::EDisplayXTwips), height);
644 __ASSERT_DEBUG(r==KErrNone && height!=0, Panic(EScreenDriverPanicInvalidHalValue));
646 return (height * 1000) / aPixels.iHeight;