Added GLES 1.x spinning cube-rendering code to eglbringuptest
The coordinate, color and index data are uploaded to server-side
buffers by the CGLES1Cube::KhrSetup function. CGLES1Cube::KhrPaint
just sets the view matrix and issues a draw command.
Which demo to display can be selected by passing its name on the
command line, e.g.
eglbringuptest vgline
eglbringuptest gles1cube
If no name is provided, the application defaults to vgline.
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
#include <graphics/wsgraphicdrawerinterface.h>
#include <e32cmn.h>
#include <u32hal.h>
#include "displaypolicy.h"
#include "panic.h"
CDisplayPolicy::CDisplayPolicy():iLastAppMode(KErrNotReady),iSmallestAppMode(KErrNotReady)
{
// No implementation required
}
CDisplayPolicy::~CDisplayPolicy()
{
}
CDisplayPolicy* CDisplayPolicy::NewLC(MWsGraphicDrawerEnvironment* aEnv,MWsScreen* aScreen,TInt aScreenNumber)
{
CDisplayPolicy* self = new (ELeave)CDisplayPolicy();
CleanupStack::PushL(self);
self->ConstructL(aEnv,aScreen,aScreenNumber);
return self;
}
CDisplayPolicy* CDisplayPolicy::NewL(MWsGraphicDrawerEnvironment* aEnv,MWsScreen* aScreen,TInt aScreenNumber)
{
CDisplayPolicy* self=CDisplayPolicy::NewLC(aEnv,aScreen,aScreenNumber);
CleanupStack::Pop(); // self;
return self;
}
void CDisplayPolicy::ConstructL(MWsGraphicDrawerEnvironment* aEnv,MWsScreen* aScreen,TInt aScreenNumber)
{
iScreenIniFile=aEnv->ObjectInterface<MWsIniFile>();
if (iScreenIniFile)
{
_LIT(KScale,"DP_SCALING");
//_LIT(KScaleNone,"none");
_LIT(KScaleInteger,"integer");
_LIT(KScaleIsotropic,"isotropic");
_LIT(KScaleAnisotropic,"anisotropic");
_LIT(KScreenDisconnected,"SIMULATE_STARTUP_DISCONNECTED");
iUiScaling = ENone;
TPtrC scalingModeName;
if (iScreenIniFile->FindVar(aScreenNumber,KScale,scalingModeName))
{
if (scalingModeName == KScaleInteger)
{
iUiScaling = EInteger;
}
else if (scalingModeName == KScaleIsotropic)
{
iUiScaling = EIsotropic;
}
else if (scalingModeName == KScaleAnisotropic)
{
iUiScaling = EAnisotropic;
}
}
if (iScreenIniFile->FindVar(aScreenNumber,KScreenDisconnected))
{
//Simulate starting up with this screen disconnected
TDisplayConnectState displayState = EDisconnect;
TInt err = UserSvr::HalFunction(EHalGroupDisplay | (aScreenNumber<<16), EDisplayHalSetDisplayState, &displayState, NULL);
STD_ASSERT_ALWAYS(err == KErrNone, EPluginPanicHalSetDisplayState);
}
}
iScreen=aScreen;
}
void CDisplayPolicy::NewAppModesAvailable()
{
//This notification allows the list to be first populated after Wserv has finished initialising itself
//It also allows for the WServ debug method CWsScreenDevice::SetCurrentScreenModeAttributes
GetAppModeList(); //get the app size mode list again because some settings have changed
}
void CDisplayPolicy::GetModeInfoL(const MWsScreenConfigList& aList,TInt aIndex,TPoint& aOffset,TSize& aSize,TAppMode& aMode)const
{
aOffset=aList.OriginL(aIndex);
aSize=aList.ScreenModeSizeInPixelsL(aIndex);
aMode.iPixels=TRect(aOffset,aSize);
aMode.iTwips=aList.ScreenModeSizeInTwipsL(aIndex);
aMode.iOrientations=aList.AvailableOrientationsL(aIndex);
}
void CDisplayPolicy::GetAppModeList()
{
if (iScreen)
{
iSmallestAppMode = KErrNotFound;
iSmallestAppSize = TSize(10000,10000);
MWsScreenConfigList* screenConfigList=iScreen->ObjectInterface<MWsScreenConfigList>();
iNumNormalAppModes=0;
TSize largestAppMode;
if (screenConfigList)
{
RArray<TInt> goodModeIndices;
if (screenConfigList->GetScreenSizeModeList(goodModeIndices)!=KErrNone)
{
//If reserve fails then list is empty later - we can't change display res from app mode request, just use current and try to centre app area
iAppModes.Reserve(goodModeIndices.Count());
//iScreenIniFile: First time in, it should be a good pointer from which to extract the basicFlags
//Repeat calls only update the values inside app mode list entries, and the ini file should not be read again.
//Specify some basic flags by reading ini file for this screen number?
TInt basicFlags=0;
//Our demo policy uses the app mode list to generate a list of virtual resolutions.
for (TInt modeIndex=0;modeIndex<goodModeIndices.Count();modeIndex++)
{
TInt modeNum=goodModeIndices[modeIndex];
TAppMode mode;
TSize size;
TPoint offset;
mode.iFlags=basicFlags;
TRAP_IGNORE(mode.iFlags|=screenConfigList->ModeFlagsL(modeNum)); //we know modeNum is valid-wont leave
//any further flags to read from ini file for this appmode on this screen number?
//Probably should ignore modes flagged with Hal or Dynamic
// at the moment we want all modes in the list!
TInt err = KErrNone;
TRAP(err,GetModeInfoL(*screenConfigList,goodModeIndices[modeIndex],offset,size,mode));
if (err == KErrNone) //should never fail - we never ask for info for a bad mode
{
if (1<<CFbsBitGc::EGraphicsOrientationRotated90&mode.iOrientations
|| 1<<CFbsBitGc::EGraphicsOrientationRotated270&mode.iOrientations)
{ //flip rect and twips
mode.iPixels = TRect(mode.iPixels.iTl.iY,mode.iPixels.iTl.iX,mode.iPixels.iBr.iY,mode.iPixels.iBr.iX);
mode.iTwips = TSize(mode.iTwips.iHeight,mode.iTwips.iWidth);
}
mode.iModeIndex=modeNum;
if (modeIndex==iAppModes.Count())
{
iAppModes.Append(mode); //can't fail if reserve succeeded
}
else if (modeIndex<iAppModes.Count())
{
iAppModes[modeIndex]=mode; //update - wserv implementation means order never changes.
}
//This is to help policy code decide what the minimum buffer size should be
//Switching between modes requiring smaller screen area than this will not invoke memory reallocation, so will not fail.
//Perhaps an implementation would also consider the current lowest physical resolution as a guide.
//The HAL mode may be significantly larger than the app modes require
if (!(mode.iFlags&(MWsScreenConfigList::EDynamic|MWsScreenConfigList::EHalDefault)))
{
TSize borderedSize=offset.AsSize()+size;
if (borderedSize.iWidth>largestAppMode.iWidth)
largestAppMode.iWidth=borderedSize.iWidth;
if (borderedSize.iHeight>largestAppMode.iHeight)
largestAppMode.iHeight=borderedSize.iHeight;
iNumNormalAppModes++;
}
//find the smallest appmode. this will be used when display is disconnected
if (!(mode.iFlags&(MWsScreenConfigList::EDynamic|MWsScreenConfigList::EHalDefault)))
{
TSize borderedSize=offset.AsSize()+size;
if(borderedSize.iWidth*borderedSize.iHeight < iSmallestAppSize.iWidth*iSmallestAppSize.iHeight)
{
iSmallestAppSize = borderedSize;
iSmallestAppMode = modeNum;
}
}
}
}
}
goodModeIndices.Close();
}
iMinUiBufferSize=largestAppMode;
}
iScreenIniFile=NULL;
}
TInt CDisplayPolicy::MapCompositionToUi(const TRect& aSource, TRect& aTarget, TBool aIsReverseMapping) const
{
// only scaling is involved in mapping from composition to UI
// no offset change
TFraction widthFraction;
TFraction heightFraction;
if ( iCompositionSizePixels.iWidth<=0
|| iUiSizePixels.iWidth<=0
|| iCompositionSizePixels.iHeight<=0
|| iUiSizePixels.iHeight<=0)
{
aTarget=aSource;
return KErrNotReady;
}
if(aIsReverseMapping)
{
//Ui to composition
widthFraction.iNumer = iCompositionSizePixels.iWidth;
widthFraction.iDenom = iUiSizePixels.iWidth;
heightFraction.iNumer = iCompositionSizePixels.iHeight;
heightFraction.iDenom = iUiSizePixels.iHeight;
}
else
{
//composition to ui
widthFraction.iNumer = iUiSizePixels.iWidth;
widthFraction.iDenom = iCompositionSizePixels.iWidth;
heightFraction.iNumer = iUiSizePixels.iHeight;
heightFraction.iDenom = iCompositionSizePixels.iHeight;
}
aTarget.iTl.iX = widthFraction * aSource.iTl.iX;
aTarget.iBr.iX = widthFraction * aSource.iBr.iX;
aTarget.iTl.iY = heightFraction * aSource.iTl.iY;
aTarget.iBr.iY = heightFraction * aSource.iBr.iY;
return KErrNone;
}
void CDisplayPolicy::MapUiToApplication(const TRect& aSource, TRect& aTarget, TBool aIsReverseMapping) const
{
// only offset is involved in mapping from Ui to App
// no scaling
TPoint offset = iAppSizePixels.iTl;;
if(aIsReverseMapping)
{
//App to ui
aTarget.iTl = aSource.iTl + offset;
aTarget.iBr = aSource.iBr + offset;
}
else
{
//Ui to App
aTarget.iTl = aSource.iTl - offset;
aTarget.iBr = aSource.iBr - offset;
}
}
TInt CDisplayPolicy::MapUiToDSA(const TRect& aSource, TRect& aTarget, TBool aIsReverseMapping) const
{
//only offset is involved in mapping from Ui to DSA
//no scaling
TPoint dsaOffset(0, 0);
MWsScreenConfig *screenConfig = iScreen->ObjectInterface<MWsScreenConfig>();
if(screenConfig)
{
dsaOffset = screenConfig->Origin();
}
TRect rectInApp;
if(aIsReverseMapping)
{
//DSA to ui
//DSA to App first
rectInApp.iTl = aSource.iTl - dsaOffset;
rectInApp.iBr = aSource.iBr - dsaOffset;
//then app to UI
MapUiToApplication(rectInApp, aTarget, ETrue);
}
else
{
//Ui to DSA
//Ui to App first
MapUiToApplication(aSource, rectInApp, EFalse);
//then app to DSA
aTarget.iTl = rectInApp.iTl + dsaOffset;
aTarget.iBr = rectInApp.iBr + dsaOffset;
}
return KErrNone;
}
TInt CDisplayPolicy::MapCoordinates(TCoordinateSpace aSourceSpace, const TRect& aSource, TCoordinateSpace aTargetSpace, TRect& aTarget) const
{
TInt returnCode=KErrNone;
switch (aSourceSpace)
{
case ECompositionSpace:
{
if(aTargetSpace == ECompositionSpace)
{
aTarget = aSource;
}
else if(aTargetSpace == EFullScreenSpace)
{
//composition to Ui
returnCode=MapCompositionToUi(aSource, aTarget, EFalse);
}
else if(aTargetSpace == EApplicationSpace)
{
//composition to App
TRect rectInUi;
returnCode=MapCompositionToUi(aSource, rectInUi, EFalse);
MapUiToApplication(rectInUi, aTarget, EFalse);
}
else if(aTargetSpace == EDirectScreenAccessSpace)
{
//composition to DSA
TRect rectInUi;
returnCode=MapCompositionToUi(aSource, rectInUi, EFalse);
if(returnCode < 0)
break;
returnCode=MapUiToDSA(rectInUi, aTarget, EFalse);
}
else
{
return KErrNotSupported;
}
}
break;
case EFullScreenSpace:
{
if(aTargetSpace == ECompositionSpace)
{
//Ui to composition
returnCode=MapCompositionToUi(aSource, aTarget, ETrue);
}
else if(aTargetSpace == EFullScreenSpace)
{
aTarget = aSource;
}
else if(aTargetSpace == EApplicationSpace)
{
//Ui to app
MapUiToApplication(aSource, aTarget, EFalse);
}
else if(aTargetSpace == EDirectScreenAccessSpace)
{
//Ui to DSA
returnCode = MapUiToDSA(aSource, aTarget, EFalse);
}
else
{
return KErrNotSupported;
}
}
break;
case EApplicationSpace:
{
if(aTargetSpace == ECompositionSpace)
{
//App to composition
TRect rectInUi;
MapUiToApplication(aSource, rectInUi, ETrue);
returnCode=MapCompositionToUi(rectInUi, aTarget, ETrue);
}
else if(aTargetSpace == EFullScreenSpace)
{
//App to Ui
MapUiToApplication(aSource, aTarget, ETrue);
}
else if(aTargetSpace == EApplicationSpace)
{
aTarget = aSource;
}
else if(aTargetSpace == EDirectScreenAccessSpace)
{
//App to DSA
TRect rectInUi;
MapUiToApplication(aSource, rectInUi, ETrue);
returnCode = MapUiToDSA(rectInUi, aTarget, EFalse);
}
else
{
return KErrNotSupported;
}
}
break;
case EDirectScreenAccessSpace:
{
if(aTargetSpace == ECompositionSpace)
{
//DSA to composition
TRect rectInUi;
returnCode = MapUiToDSA(aSource, rectInUi, ETrue);
if(returnCode < KErrNone)
break;
returnCode = MapCompositionToUi(rectInUi, aTarget, ETrue);
}
else if(aTargetSpace == EFullScreenSpace)
{
//DSA to Ui
returnCode = MapUiToDSA(aSource, aTarget, ETrue);
}
else if(aTargetSpace == EApplicationSpace)
{
//DSA to app
TRect rectInUi;
returnCode = MapUiToDSA(aSource, rectInUi, ETrue);
MapUiToApplication(rectInUi, aTarget, EFalse);
}
else if(aTargetSpace == EDirectScreenAccessSpace)
{
aTarget = aSource;
}
else
{
return KErrNotSupported;
}
break;
}
default:
returnCode= KErrNotSupported;
}
return returnCode;
}
CDisplayPolicy::TFraction::TFraction():iNumer(0),iDenom(1)
{}
TInt CDisplayPolicy::TFraction::operator*(TInt aInt) const
{
if (iDenom == 0 || iNumer == 0 || aInt == 0)
{
return 0;
}
TInt aNumer = iNumer<<1;
TInt aDenom = iDenom;
TInt returnValue = (aNumer*aInt)/aDenom;
returnValue ++;
return returnValue>>1;
}
void CDisplayPolicy::CalculateMinBufferSize(RArray<MDisplayControlBase::TResolution>& aResolutions, TInt aConnectionStatus)
{
iConnectionStatus = aConnectionStatus;
//preq2102: aResolutions is likely to be changed (in future)
if(iUiScaling == ENone)
{
//this function is currently only used with no scaling
//should not be called when display is disconnected
//with scaling iMinUiBufferSize is calculated in CDisplayPolicy::GetAppModeList()
TSize largestPhysicalRes = iMinUiBufferSize;
for(TInt i = 0;i < aResolutions.Count(); i++)
{
if(aResolutions[i].iPixelSize.iWidth > largestPhysicalRes.iWidth)
{
largestPhysicalRes.iWidth = aResolutions[i].iPixelSize.iWidth;
}
if(aResolutions[i].iPixelSize.iHeight > largestPhysicalRes.iHeight)
{
largestPhysicalRes.iHeight = aResolutions[i].iPixelSize.iHeight;
}
}
iMinUiBufferSize = largestPhysicalRes;
}
}
void CDisplayPolicy::AdjustStageBufferSize(const TSize& /*aOldSize*/,TSize& aNewSize)
{
if (iMinUiBufferSize.iWidth==0)
{
//just in case, should never happen
iMinUiBufferSize=TSize(1,1);
}
if ((aNewSize.iWidth == 0 || aNewSize.iHeight == 0
|| iConnectionStatus <= 0) && iUiScaling != ENone
&& iSmallestAppMode >= 0) // if detached or turned off (iUiScaling != ENone) and smallestAppMode is found
{
aNewSize = iSmallestAppSize;
return;
}
if (aNewSize.iWidth < iMinUiBufferSize.iWidth)
{
aNewSize.iWidth = iMinUiBufferSize.iWidth;
}
if (aNewSize.iHeight < iMinUiBufferSize.iHeight)
{
aNewSize.iHeight = iMinUiBufferSize.iHeight;
}
}
void CDisplayPolicy::AddVirtualResolutionCount(TInt& aDisplayCount) const
{
if (iUiScaling != ENone && aDisplayCount>0)
{
aDisplayCount += iNumNormalAppModes;
}
}
TInt CDisplayPolicy::AddVirtualResolutions(RArray<MDisplayControlBase::TResolution>& aResolutions) const
{
if (aResolutions.Count()==0 || iUiScaling == ENone)
{
return KErrNone;
}
if (aResolutions.Count()==1 && aResolutions[0].iPixelSize==TSize(0,0))
{
return KErrNone;
}
TInt appModeCount = iAppModes.Count();
if (appModeCount == 0)
{
return KErrNone;
}
TInt resolutionCount = aResolutions.Count();
TInt error = aResolutions.Reserve(iNumNormalAppModes + resolutionCount);
if (error < KErrNone)
{
aResolutions.Reset();
return error; //could fail to reserve if out of memory
}
for (TInt appMode = 0; appMode < appModeCount; appMode++)
{
if (!(iAppModes[appMode].iFlags&(MWsScreenConfigList::EDynamic|MWsScreenConfigList::EHalDefault)))
{
MDisplayControlBase::TResolution virtualResolution = AppModeToResolution(aResolutions,appMode);
aResolutions.Append(virtualResolution);
}
}
return KErrNone;
}
MDisplayControlBase::TResolution CDisplayPolicy::AppModeToResolution(RArray<MDisplayControlBase::TResolution>& aResolutions,TInt appMode)const
{
TAppMode mode = iAppModes[appMode];
TBool notComplete = ETrue;
TInt bestIndex;
TInt bestScale;
MDisplayControlBase::TResolution tempResolution(TSize(0,0),TSize(0,0));
TSize appBestSize;
while (notComplete)
{
TBool modeFit = FindVirtualMode(aResolutions,mode,appBestSize,bestIndex,bestScale);
TSize uiSize;
if (iUiScaling == EInteger || iUiScaling == EIsotropic)
{
uiSize = ResolutionSize(aResolutions,appBestSize,bestIndex,bestScale);
}
else if (iUiScaling == EAnisotropic)
{
TBool swapAxis = EFalse;
TBool fitsAppMode = EFalse;
while (!fitsAppMode)
{
if (iAppModes[appMode].iFlags&MWsScreenConfigList::ETwipsSpecified)
{
//virtualResolution.iTwipsSize = aResolutions[bestIndex].iTwipsSize;
//calculate based on twips
uiSize = ResolutionSizeFromTwips(aResolutions,appMode,appBestSize,bestIndex,swapAxis);
}
else
{
//assume square pixels
//virtualResolution.iTwipsSize = aResolutions[bestIndex].iTwipsSize;
uiSize = ResolutionSizeFromAssumedTwips(aResolutions,appBestSize,bestIndex,swapAxis,bestScale);
}
//if pixelsize found is larger than resolution mode its designed for, try scaling using other axis
if (uiSize.iWidth > aResolutions[bestIndex].iPixelSize.iWidth ||
uiSize.iHeight > aResolutions[bestIndex].iPixelSize.iHeight)
{
if (!modeFit) //no other mode it could fit, to avoid infinite loop,say it fits the mode - will be scaled down
{
fitsAppMode = ETrue;
}
else
{
STD_ASSERT_DEBUG(swapAxis == EFalse, EPluginPanicTemp);
swapAxis = ETrue;
}
}
else
{
fitsAppMode = ETrue;
}
}
//if pixelsize found does not fit app mode, must retry with an appmode larger than the one found
if (uiSize.iWidth < iAppModes[appMode].iPixels.iBr.iX ||
uiSize.iHeight < iAppModes[appMode].iPixels.iBr.iY)
{
mode.iPixels.iBr.iX = aResolutions[bestIndex].iPixelSize.iWidth+1;
mode.iPixels.iBr.iY = aResolutions[bestIndex].iPixelSize.iHeight+1;
continue;
}
}
//MDisplayControlBase::TResolution virtualResolution(TSize(0,0),TSize(0,0));
//only supports rotations supported by both sizemode and hardware
tempResolution.iFlags = iAppModes[appMode].iOrientations&aResolutions[bestIndex].iFlags.iFlags;
tempResolution.iFlags.Set(MDisplayControlBase::TResolution::EIsVirtual);
tempResolution.iTwipsSize = aResolutions[bestIndex].iTwipsSize;
tempResolution.iPixelSize = uiSize;
notComplete = EFalse; //found a resolution that fits!
}
return tempResolution;
}
TBool CDisplayPolicy::MatchConfigToResolutions(const RArray<MDisplayControlBase::TResolution>& aResolutions,
const TDisplayConfiguration& aConfig, TInt aStartIndex, TInt& aResolutionIndex)const
{
if (aStartIndex < 0 || aStartIndex >= aResolutions.Count())
{
return EFalse;
}
aResolutionIndex = -1;
for (TInt i = aStartIndex; i < aResolutions.Count(); i++)
{
if (aConfig.IsDefined(TDisplayConfigurationBase::EResolution))
{
TSize resolution;
aConfig.GetResolution(resolution);
if (resolution != aResolutions[i].iPixelSize)
{
continue;
}
}
if (aConfig.IsDefined(TDisplayConfigurationBase::EResolutionTwips))
{
TSize twips;
aConfig.GetResolutionTwips(twips);
if (twips != aResolutions[i].iTwipsSize)
{
continue;
}
}
if (aConfig.IsDefined(TDisplayConfigurationBase::ERotation))
{
TDisplayConfiguration1::TRotation rotation;
aConfig.GetRotation(rotation);
if (aResolutions[i].iFlags.IsClear(rotation))
{
continue;
}
}
aResolutionIndex = i;
return ETrue;
}
return EFalse;
}
/*
Checks if specified appmode is compatible with TResolution specified
Returns ETrue if succeeded (and fills aConfig with TResolution
Return EFalse if they are not compatible (will not touch the config)
*/
TBool CDisplayPolicy::SetConfigToResolution(TInt aAppMode, MDisplayControlBase::TResolution aResolution, TDisplayConfiguration& aConfig)const
{
//find intersection of appmode and hardware rotations
TDisplayConfiguration1::TRotation configRotation;
TInt compatibleRotations;
if (aConfig.GetRotation(configRotation))
{
compatibleRotations = iAppModes[aAppMode].iOrientations&aResolution.iFlags.iFlags&0xF&(1<<configRotation);
}
else
{
compatibleRotations = iAppModes[aAppMode].iOrientations&aResolution.iFlags.iFlags&0xF;
}
if (compatibleRotations > 0)
{ //set first compatible rotation we find
if (1<<CFbsBitGc::EGraphicsOrientationNormal & compatibleRotations)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotationNormal);
}
else if (1<<CFbsBitGc::EGraphicsOrientationRotated90 & compatibleRotations)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotation90CW);
}
else if (1<<CFbsBitGc::EGraphicsOrientationRotated180 & compatibleRotations)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotation180);
}
else
{
aConfig.SetRotation(TDisplayConfiguration1::ERotation270CW);
}
aConfig.SetResolution(aResolution.iPixelSize);
aConfig.SetResolutionTwips(aResolution.iTwipsSize);
return ETrue;
}
return EFalse;
}
TInt CDisplayPolicy::GetSizeModeConfiguration(RArray<MDisplayControlBase::TResolution>& aResolutions,
TInt aScreenSizeMode, TDisplayConfiguration& aConfig, TRect& aSizeModePosition) const
{
//find appMode corresponding to screensizemode
TInt appMode;
TInt appModeCount = iAppModes.Count();
for (appMode = 0; appMode < appModeCount; appMode++)
{
if (iAppModes[appMode].iModeIndex == aScreenSizeMode)
{
break;
}
}
if (appModeCount == appMode)
{
return KErrArgument; //invalid screen size mode
}
if (!aConfig.IsDefined(TDisplayConfigurationBase::EResolution)&&
!aConfig.IsDefined(TDisplayConfigurationBase::EResolutionTwips))
{
if (iAppModes[appMode].iFlags&MWsScreenConfigList::EDynamic)
{
TSize resSize = iCompositionSizePixels;
TSize twipsSize = iCompositionSizeTwips;
if (iLastCompositionRotation&TDisplayConfiguration::ERotation90CW ||
iLastCompositionRotation&TDisplayConfiguration::ERotation270CW)
{
TInt tempVal = resSize.iWidth;
resSize.iWidth = resSize.iHeight;
resSize.iHeight = tempVal;
tempVal = twipsSize.iWidth;
twipsSize.iWidth = twipsSize.iHeight;
twipsSize.iHeight = tempVal;
}
aConfig.SetResolution(resSize);
aConfig.SetResolutionTwips(twipsSize);
}
else
{
MDisplayControlBase::TResolution virtualResolution = AppModeToResolution(aResolutions,appMode);
aConfig.SetResolution(virtualResolution.iPixelSize);
aConfig.SetResolutionTwips(virtualResolution.iTwipsSize);
}
}
//check config is valid from set of resolutions (inc virtual)
TInt error = AddVirtualResolutions(aResolutions);
if (error < KErrNone)
{
return error;
}
TInt startIndex=0;
while (startIndex < aResolutions.Count())
{
TInt resolutionIndex;
TBool boolError = MatchConfigToResolutions(aResolutions,aConfig,startIndex,resolutionIndex);
if (boolError == EFalse)
{
return KErrArgument;
}
//if is larger than current app mode and same rotation,we have found a match and can break;
TBool boolSet = SetConfigToResolution(appMode,aResolutions[resolutionIndex],aConfig);
if (boolSet)
{ //new configuration is compatible with app mode and has been set
//center appmode within the UI
if (iAppModes[appMode].iFlags&MWsScreenConfigList::EDynamic)
{
aSizeModePosition = aResolutions[resolutionIndex].iPixelSize;
}
else
{
CenteredAppInUi(aResolutions[resolutionIndex].iPixelSize,iAppModes[appMode].iPixels,aSizeModePosition);
}
TDisplayConfiguration::TRotation tempRot;
aConfig.GetRotation(tempRot);
if (tempRot&1)
{
aSizeModePosition = TRect(aSizeModePosition.iTl.iY,aSizeModePosition.iTl.iX,
aSizeModePosition.iBr.iY,aSizeModePosition.iBr.iX);
}
return KErrNone;
}
//otherwise
startIndex = resolutionIndex+1; //match found will not fit current size mode, continue looking
if (startIndex == aResolutions.Count())
{
return KErrArgument;
}
}
STD_ASSERT_DEBUG(EFalse, EPluginPanicTemp);
return KErrGeneral; //shouldnt be able to get here
}
void CDisplayPolicy::CenteredAppInUi(const TSize& aUiSize,const TRect& aAppExtent,TRect& aSizeModePosition) const
{
if (aUiSize.iWidth > aAppExtent.Width())
{
aSizeModePosition.iTl.iX = (aUiSize.iWidth - aAppExtent.Width()) / 2;
if (aSizeModePosition.iTl.iX < aAppExtent.iTl.iX)
{ //we want to obey screenmode offset as a minumum, so cannot center on this axis
aSizeModePosition.iTl.iX = aAppExtent.iTl.iX;
aSizeModePosition.iBr.iX = aAppExtent.iBr.iX;
}
else
{
aSizeModePosition.iBr.iX = aSizeModePosition.iTl.iX + aAppExtent.Width();
}
}
else
{
aSizeModePosition.iTl.iX = aAppExtent.iTl.iX;
aSizeModePosition.iBr.iX = aAppExtent.iBr.iX;
}
if (aUiSize.iHeight > aAppExtent.Height())
{
aSizeModePosition.iTl.iY = (aUiSize.iHeight - aAppExtent.Height()) / 2;
if (aSizeModePosition.iTl.iY < aAppExtent.iTl.iY)
{ //we want to obey screenmode offset as a minumum, so cannot center on this axis
aSizeModePosition.iTl.iY = aAppExtent.iTl.iY;
aSizeModePosition.iBr.iY = aAppExtent.iBr.iY;
}
else
{
aSizeModePosition.iBr.iY = aSizeModePosition.iTl.iY + aAppExtent.Width();
}
}
else
{
aSizeModePosition.iTl.iY = aAppExtent.iTl.iY;
aSizeModePosition.iBr.iY = aAppExtent.iBr.iY;
}
}
TInt CDisplayPolicy::GetSizeModeConfiguration(TInt aScreenSizeMode,TDisplayConfiguration& aConfig, TRect& aSizeModePosition)
{
//This function is used when display is disconnected. Set UI size same as app mode. We don't care about rotation
//find appMode corresponding to screensizemode
TInt appMode;
TInt appModeCount = iAppModes.Count();
for (appMode = 0; appMode < appModeCount; appMode++)
{
if (iAppModes[appMode].iModeIndex == aScreenSizeMode)
{
break;
}
}
if (appModeCount == appMode)
{
return KErrArgument; //invalid screen size mode
}
if (1<<CFbsBitGc::EGraphicsOrientationRotated90&iAppModes[appMode].iOrientations
|| 1<<CFbsBitGc::EGraphicsOrientationRotated270&iAppModes[appMode].iOrientations)
{//width and height were already flipped on construction. we need to flip it back
TRect appRect = iAppModes[appMode].iPixels;
TRect uiResRect(appRect.iTl.iX, appRect.iTl.iY, appRect.iBr.iY, appRect.iBr.iX);
aConfig.SetResolution(uiResRect.Size());
}
else
{
aConfig.SetResolution(iAppModes[appMode].iPixels.iBr.AsSize());
}
CFbsBitGc::TGraphicsOrientation cFbsOrientation=CFbsBitGc::EGraphicsOrientationNormal;
//we know aScreenSizeMode is valid-OrientationL wont leave
TRAP_IGNORE(cFbsOrientation=iScreen->ObjectInterface<MWsScreenConfigList>()->OrientationL(aScreenSizeMode));
aConfig.SetRotation(TDisplayConfiguration::TRotation(cFbsOrientation));
aSizeModePosition = iAppModes[appMode].iPixels;
return KErrNone;
}
TBool CDisplayPolicy::SettingConfiguration(const RArray<MDisplayControlBase::TResolution>& aResolutions,TDisplayConfiguration& aConfig)const
{ //converts configuration to appmode
if (iUiScaling == ENone)
{
if (aConfig.IsDefined(aConfig.EResolution))
{
TSize res;
aConfig.GetResolution(res);
TInt index;
for (index=0;index<aResolutions.Count();index++)
{
if (aResolutions[index].iPixelSize == res)
{
break;
}
}
if (index == aResolutions.Count())
{ //failed to validate the resolution
aConfig.Clear(aConfig.EResolution);
}
}
return EFalse;
}
TAppMode appMode;
TBool set;
TRect zeroRect (0,0,0,0);
TSize zeroSize (0,0);
TSize size;
set = aConfig.GetResolution(size);
appMode.iPixels = set ? size : zeroRect;
set = aConfig.GetResolutionTwips(size);
appMode.iTwips = set ? size : zeroSize;
TDisplayConfiguration::TRotation flags;
set = aConfig.GetRotation(flags); //grr orientation again
appMode.iOrientations = set? flags : 0; //will set the specific rotation
TInt index=0;
TInt scale=0;
TSize bestAppSize;
FindVirtualMode(aResolutions,appMode,bestAppSize,index,scale);
//set aConfig to resolution returned
aConfig.SetResolution(aResolutions[index].iPixelSize);
aConfig.SetResolutionTwips(aResolutions[index].iTwipsSize);
if (aResolutions[index].iFlags.IsSet(MDisplayControlBase::TResolution::ERotationNormalSupported)
&& appMode.iOrientations == TDisplayConfiguration::ERotationNormal)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotationNormal);
}
else if (aResolutions[index].iFlags.IsSet(MDisplayControlBase::TResolution::ERotation90Supported)
&& appMode.iOrientations == TDisplayConfiguration::ERotation90CW)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotation90CW);
}
else if (aResolutions[index].iFlags.IsSet(MDisplayControlBase::TResolution::ERotation180Supported)
&& appMode.iOrientations == TDisplayConfiguration::ERotation180)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotation180);
}
else if (aResolutions[index].iFlags.IsSet(MDisplayControlBase::TResolution::ERotation270Supported)
&& appMode.iOrientations == TDisplayConfiguration::ERotation270CW)
{
aConfig.SetRotation(TDisplayConfiguration1::ERotation270CW);
}
else
{
STD_ASSERT_DEBUG(EFalse, EPluginPanicTemp);
return EFalse;
}
return ETrue;
}
void CDisplayPolicy::SetCompositionInfo (const TDisplayConfiguration& aCompositionConfig,
const TDisplayConfiguration& aUiConfig)
{
TDisplayConfiguration::TRotation rotation;
TSize sizePixels;
TSize sizeTwips;
if (aCompositionConfig.GetResolution(sizePixels))
{
aCompositionConfig.GetResolutionTwips(sizeTwips);
if(aCompositionConfig.IsDefined(TDisplayConfiguration::ERotation))
{
aCompositionConfig.GetRotation(rotation);
iLastCompositionRotation=rotation;
if(rotation & TDisplayConfiguration::ERotation90CW)
{
//swap width and height to be stored in iCompositionSizePixels and iCompositionSizeTwips
iCompositionSizePixels.iHeight = sizePixels.iWidth;
iCompositionSizePixels.iWidth = sizePixels.iHeight;
iCompositionSizeTwips.iHeight = sizeTwips.iWidth;
iCompositionSizeTwips.iWidth = sizeTwips.iHeight;
}
else
{
iCompositionSizePixels = sizePixels;
iCompositionSizeTwips = sizeTwips;
}
}
else
{
iCompositionSizePixels = sizePixels;
iCompositionSizeTwips = sizeTwips;
}
aUiConfig.GetResolution(sizePixels);
aUiConfig.GetResolutionTwips(sizeTwips);
if(aUiConfig.IsDefined(TDisplayConfiguration::ERotation))
{
aUiConfig.GetRotation(rotation);
iLastUiRotation=rotation;
if(rotation & TDisplayConfiguration::ERotation90CW)
{
//swap width and height to be stored in iUiSizePixels and iAppSizeTwips
iUiSizePixels.iHeight = sizePixels.iWidth;
iUiSizePixels.iWidth = sizePixels.iHeight;
iAppSizeTwips.iHeight = sizeTwips.iWidth;
iAppSizeTwips.iWidth = sizeTwips.iHeight;
}
else
{
iUiSizePixels = sizePixels;
iAppSizeTwips = sizeTwips;
}
}
else
{
iUiSizePixels = sizePixels;
iAppSizeTwips = sizeTwips;
}
}
else
{
if (aUiConfig.GetRotation(rotation))
{
if ((rotation^iLastUiRotation)&TDisplayConfiguration::ERotation90CW)
{
TInt swapHeight=iUiSizePixels.iHeight;
iUiSizePixels.iHeight = iUiSizePixels.iWidth;
iUiSizePixels.iWidth = swapHeight;
}
iLastUiRotation=rotation;
}
if (aCompositionConfig.GetRotation(rotation))
{
if ((rotation^iLastCompositionRotation)&TDisplayConfiguration::ERotation90CW)
{
TInt swapHeight=iCompositionSizePixels.iHeight;
iCompositionSizePixels.iHeight = iCompositionSizePixels.iWidth;
iCompositionSizePixels.iWidth = swapHeight;
swapHeight=iCompositionSizeTwips.iHeight;
iCompositionSizeTwips.iHeight = iCompositionSizeTwips.iWidth;
iCompositionSizeTwips.iWidth = swapHeight;
}
iLastCompositionRotation=rotation;
}
}
}
void CDisplayPolicy::SetSizeModeExtent(TRect& aExtent, TBitFlags32 /*aContext*/)
{
iAppSizePixels = aExtent;
}
/** Finds the best resolution that the specified appmode can fit into
Returns ETrue if it fits a mode
Returns EFalse to warn if it didnt fit in that mode
For both, it will set index and scale to the best fit
*/
TBool CDisplayPolicy::FindVirtualMode(const RArray<MDisplayControlBase::TResolution>& aResolutions,
const CDisplayPolicy::TAppMode& aAppMode,TSize& aFullAppModeSize,TInt& aIndex,TInt& aBestScale) const
{
const TInt KBestFit = 0x7000000; //a really big number that should get reduced during the search.
TInt bestFit=KBestFit;
TInt resDiffX;
TInt resDiffY;
TInt64 biggestArea(0);
TInt biggestAreaIndex=0;
TBool fullAppSize;
if (aAppMode.iPixels.iTl.iX == 0 && aAppMode.iPixels.iTl.iY == 0)
{ //no point trying again with a border on only 2 sides, as there is no border anyway!
fullAppSize = EFalse;
}
else
{
fullAppSize = ETrue;
}
aFullAppModeSize = TSize(aAppMode.iPixels.iBr.iX + aAppMode.iPixels.iTl.iX,
aAppMode.iPixels.iBr.iY + aAppMode.iPixels.iTl.iY); //try fitting with border all 4 sides
while(1)
{
//find hardware mode that fits this best
for (TInt j = 0; j < aResolutions.Count(); j++)
{
if (bestFit == 0)
{ //found a perfect match
break;
}
if (aResolutions[j].iFlags[MDisplayControlBase::TResolution::EIsVirtual])
{ //ignore virtual resolutions
continue;
}
TInt maxScaling = 1;
if (iUiScaling == EInteger)
{
maxScaling = 4;
}
for (TInt k = maxScaling; k > 0; k--)
{ //for every avalable integer scale
if (bestFit == 0)
{ //found a perfect match
break;
}
TInt64 area=TInt64(aResolutions[j].iPixelSize.iWidth)*aResolutions[j].iPixelSize.iHeight;
if (area>biggestArea)
{
biggestArea=area;
biggestAreaIndex=j;
}
resDiffX = (aResolutions[j].iPixelSize.iWidth/k) - aFullAppModeSize.iWidth;
resDiffY = (aResolutions[j].iPixelSize.iHeight/k) - aFullAppModeSize.iHeight;
if (resDiffX < 0 || resDiffY < 0)
{ //app mode too large for this resolution
continue;
}
if (resDiffX+resDiffY < bestFit)
{
aIndex = j;
bestFit = resDiffX + resDiffY;
aBestScale = k;
continue;
}
}
}
if (bestFit != KBestFit)
{ //it found the best resolution to scale into
break;
}
else if (fullAppSize == EFalse)
{ //app does not fit any resolution, it will have to be scaled down to fit
aIndex=biggestAreaIndex;
aBestScale=1;
return EFalse;
}
else
{
aFullAppModeSize = TSize(aAppMode.iPixels.iBr.iX,
aAppMode.iPixels.iBr.iY); //try fitting with border only top and left
fullAppSize = EFalse;
}
}
return ETrue;
}
TSize CDisplayPolicy::ResolutionSize(RArray<MDisplayControlBase::TResolution>& aResolutions,
const TSize aBestAppSize,TInt aIndex, TInt aScale) const
{
TSize returnSize;
if (iUiScaling == EInteger) //only supporting integral scales
{ //just calculate the scaled resolution
returnSize = TSize(aResolutions[aIndex].iPixelSize.iWidth/aScale,
aResolutions[aIndex].iPixelSize.iHeight/aScale);
}
else
{ //find which axis scales best, create virtual resolution that fits this axis
TFraction bestAxisAsFraction;
if ((TInt64)aResolutions[aIndex].iPixelSize.iWidth * aBestAppSize.iHeight >
(TInt64)aResolutions[aIndex].iPixelSize.iHeight * aBestAppSize.iWidth)
{ //y axis scales closest
bestAxisAsFraction.iNumer = aResolutions[aIndex].iPixelSize.iWidth;
bestAxisAsFraction.iDenom = aResolutions[aIndex].iPixelSize.iHeight;
returnSize = TSize(bestAxisAsFraction*aBestAppSize.iHeight,
aBestAppSize.iHeight);
}
else
{ //x axis scales closest
bestAxisAsFraction.iNumer = aResolutions[aIndex].iPixelSize.iHeight;
bestAxisAsFraction.iDenom = aResolutions[aIndex].iPixelSize.iWidth;
returnSize = TSize(aBestAppSize.iWidth,
bestAxisAsFraction*aBestAppSize.iWidth);
}
}
return returnSize;
}
TSize CDisplayPolicy::GetUiResolution()
{
return this->iUiSizePixels;
}
TSize CDisplayPolicy::GetUiResolutionAsTwips() const
{
return this->iCompositionSizeTwips;
}
TRect CDisplayPolicy::GetPolicyAppMode()
{
return iAppSizePixels;
}
TSize CDisplayPolicy::ResolutionSizeFromTwips(RArray<MDisplayControlBase::TResolution>& aResolutions, TInt aAppMode, const TSize& aBestAppSize,
TInt aIndex,TBool aSwapAxis) const
{
TSize returnSize;
TFraction tempFraction;
TBool yScalesClosest;
if ((TInt64)aResolutions[aIndex].iPixelSize.iWidth * aBestAppSize.iHeight > (TInt64)aResolutions[aIndex].iPixelSize.iHeight * aBestAppSize.iWidth)
{ //y axis scales closest
yScalesClosest = aSwapAxis?EFalse:ETrue;
}
else
{ //x axis scales closest
yScalesClosest = aSwapAxis?ETrue:EFalse;
}
if (yScalesClosest)
{ //y axis scales closest
tempFraction.iNumer = aBestAppSize.iHeight; //bordered app height in pixels
tempFraction.iDenom = iAppModes[aAppMode].iPixels.iBr.iY - iAppModes[aAppMode].iPixels.iTl.iY; //app height in pixels
TInt uiYTwips=tempFraction*iAppModes[aAppMode].iTwips.iHeight; //bordered app height in twips
tempFraction.iNumer = aResolutions[aIndex].iTwipsSize.iWidth; //display width in twips
tempFraction.iDenom = aResolutions[aIndex].iTwipsSize.iHeight; //display height in twips
TInt uiXTwips=tempFraction*uiYTwips; //virtual width in twips
tempFraction.iNumer = iAppModes[aAppMode].iPixels.iBr.iX - iAppModes[aAppMode].iPixels.iTl.iX; //app width in pixels
tempFraction.iDenom = iAppModes[aAppMode].iTwips.iWidth; //display width in twips
TInt uiXPixels=tempFraction*uiXTwips; //virtual width in pixels
returnSize.iWidth = uiXPixels;
returnSize.iHeight = aBestAppSize.iHeight;
}
else
{ //x axis scales closest
tempFraction.iNumer = aBestAppSize.iWidth; //bordered app width in pixels
tempFraction.iDenom = iAppModes[aAppMode].iPixels.iBr.iX - iAppModes[aAppMode].iPixels.iTl.iX; //app width in pixels
TInt uiXTwips=tempFraction*iAppModes[aAppMode].iTwips.iWidth; //bordered app width in twips
tempFraction.iNumer = aResolutions[aIndex].iTwipsSize.iHeight; //display height in twips
tempFraction.iDenom = aResolutions[aIndex].iTwipsSize.iWidth; //display width in twips
TInt uiYTwips=tempFraction*uiXTwips; //virtual height in twips
tempFraction.iNumer = iAppModes[aAppMode].iPixels.iBr.iY - iAppModes[aAppMode].iPixels.iTl.iY; //app height in pixels
tempFraction.iDenom = iAppModes[aAppMode].iTwips.iHeight; //display height in twips
TInt uiYPixels=tempFraction*uiYTwips; //virtual width in pixels
returnSize.iWidth = aBestAppSize.iWidth;
returnSize.iHeight = uiYPixels;
}
return returnSize;
}
TSize CDisplayPolicy::ResolutionSizeFromAssumedTwips(RArray<MDisplayControlBase::TResolution>& aResolutions,const TSize& aBestAppSize,
TInt aIndex,TBool aSwapAxis, TInt aScale) const
{
TSize returnSize;
if (iUiScaling == EInteger) //only supporting integral scales
{ //just calculate the scaled resolution
returnSize = TSize(aResolutions[aIndex].iTwipsSize.iWidth/aScale,
aResolutions[aIndex].iTwipsSize.iHeight/aScale);
}
else
{ //find which axis scales best, create virtual resolution that fits this axis
TBool yScalesClosest;
TFraction bestAxisAsFraction;
if ((TInt64)aResolutions[aIndex].iPixelSize.iWidth * aBestAppSize.iHeight >
(TInt64)aResolutions[aIndex].iPixelSize.iHeight * aBestAppSize.iWidth)
{ //y axis scales closest
yScalesClosest = aSwapAxis?EFalse:ETrue;
}
else
{ //x axis scales closest
yScalesClosest = aSwapAxis?ETrue:EFalse;
}
if (yScalesClosest)
{ //y axis scales closest
bestAxisAsFraction.iNumer = aResolutions[aIndex].iTwipsSize.iWidth;
bestAxisAsFraction.iDenom = aResolutions[aIndex].iTwipsSize.iHeight;
returnSize = TSize(bestAxisAsFraction*aBestAppSize.iHeight,
aBestAppSize.iHeight);
}
else
{ //x axis scales closest
bestAxisAsFraction.iNumer = aResolutions[aIndex].iTwipsSize.iHeight;
bestAxisAsFraction.iDenom = aResolutions[aIndex].iTwipsSize.iWidth;
returnSize = TSize(aBestAppSize.iWidth,
bestAxisAsFraction*aBestAppSize.iWidth);
}
}
return returnSize;
}
TInt CDisplayPolicy::MinSizedModeIndex()
{
return iSmallestAppMode;
}
TInt CDisplayPolicy::SuitableAppMode(MWsDisplayPolicy::TDisplayStatus aSituation)
{
switch(aSituation)
{
case MWsDisplayPolicy::EAttach:
{
return iLastAppMode;
}
case MWsDisplayPolicy::EDetach:
{
return MinSizedModeIndex();
}
default:
return KErrNotSupported;
}
}
void CDisplayPolicy::SetLastAppMode(TInt aMode)
{
iLastAppMode = aMode;
}