diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiEnv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiEnv.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,1764 @@ +/* +* Copyright (c) 2006-2007 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: Implementation of CHuiEnv, a common working environment for the Toolkit. +* +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "uiacceltk/HuiEnv.h" // Class definition +#include +#include "HuiRenderPlugin.h" +#include "uiacceltk/HuiStatic.h" +#include "alf/alfconstants.h" +#include "HuiRenderSurface.h" +#include "uiacceltk/HuiDisplay.h" +#include "HuiRosterImpl.h" +#include "uiacceltk/HuiScheduler.h" +#include "uiacceltk/HuiTextureManager.h" +#include "uiacceltk/HuiControlGroup.h" +#include "HuiVisualFactory.h" +#include "uiacceltk/HuiS60Skin.h" +#include "uiacceltk/HuiEvent.h" +#include "uiacceltk/HuiRoster.h" +#include "uiacceltk/HuiUtil.h" +#include "uiacceltk/HuiPanic.h" +#include "uiacceltk/huitextstylemanager.h" +#include "huistatictlsdata.h" +#include "uiacceltk/HuiThemeManager.h" +#include "huicanvastexturecache.h" +#include "HuiFxEngine.h" + +#define HUI_HIRES_TIMER + + +/* Constants */ + +// Until we get refresh interval issues solved (implement hi-res timer), this define keeps fps at respectable enough level +#ifdef SYMBIAN_BUILD_GCE +#define HUI_NGA_MIN_REFRESH_INTERVAL +#endif + +// This is for testing, can be used to force forced refresh +#ifdef SYMBIAN_BUILD_GCE +//#define HUI_NGA_FORCED_REFRESH +#endif + +// This is for testing, prints performance information +//#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + +#ifdef SYMBIAN_BUILD_GCE + #ifdef __WINSCW__ + const TInt KHuiEnvDefaultNormalRefreshIntervalMs = 40; + const TInt KHuiEnvDefaultBusyRefreshIntervalMs = 40; + #else + const TInt KHuiEnvDefaultNormalRefreshIntervalMs = 15; + const TInt KHuiEnvDefaultBusyRefreshIntervalMs = 15; + #endif +#else +const TInt KHuiEnvDefaultNormalRefreshIntervalMs = 20; +const TInt KHuiEnvDefaultBusyRefreshIntervalMs = 2 * KHuiEnvDefaultNormalRefreshIntervalMs; +#endif + + +#ifndef SYMBIAN_BUILD_GCE +const TUint KHuiEnvMaxCpuTime = 100; +#endif +const TUint KRndTexMemCalcFlag = 0x800; + +/* If there is idle between frames, this is how much we can use as overdrive max cpu utilisation */ +const TUint KHuiEnvMaxCpuTimeOverdriveMaxValue = 100; + +/* If max cpu usage has been set below this value, overdrive is not used because there is probaply a good reson +for a low max cpu usage value */ +const TUint KHuiEnvMaxCpuTimeOverdriveLowerThreshold = 50; + + +/** Threshold number for refreshes that don't have any effect. When exceeded, + refresh is paused. */ +const TInt KIdleRefreshCountThreshold = 3; + +const THuiRefreshMode KHuiDefaultRefreshMode = EHuiRefreshModeAutomatic; +class CHighResTimer : public CTimer + { +public: + static CHighResTimer* NewL(TCallBack aCallBack, TInt aPriority) + { + CHighResTimer* self = new(ELeave) CHighResTimer(aCallBack, aPriority); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + ~CHighResTimer() + { + Cancel(); + } + + void CallBack(const TInt aWaitInMilliSecs) + { + TInt wait = 1000*aWaitInMilliSecs; + if (wait < 0) + { + wait = 15000; + } + else if (wait > 60000) + { + wait = 60000; + } + + HighRes( TTimeIntervalMicroSeconds32( wait ) ); + } + +private: + CHighResTimer(TCallBack aCallBack, TInt aPriority) + : CTimer(aPriority), iCallBack(aCallBack) + { + CActiveScheduler::Add(this); + } + + void RunL() + { + iCallBack.CallBack(); + } + + TCallBack iCallBack; + }; + +EXPORT_C CHuiEnv* CHuiEnv::NewL(THuiRenderer aRenderer, MHuiEnvObserver* aObserver) + { + CHuiEnv* self = CHuiEnv::NewLC(aRenderer, aObserver); + CleanupStack::Pop(self); + return self; + } + + +EXPORT_C CHuiEnv* CHuiEnv::NewLC(THuiRenderer aRenderer, MHuiEnvObserver* aObserver) + { + CHuiEnv* self = new (ELeave) CHuiEnv(aObserver); + CleanupStack::PushL(self); + self->ConstructL(aRenderer); + + return self; + } + + +CHuiEnv::CHuiEnv(MHuiEnvObserver* aObserver) + : iState(ENormal), + iRefreshMode(KHuiDefaultRefreshMode), + iRefreshInterval(KHuiEnvDefaultNormalRefreshIntervalMs), + iRefreshIntervalTarget(KHuiEnvDefaultNormalRefreshIntervalMs), + iEnvObserver(aObserver), + iIdleThreshold(10), + iMaxCPUUtilization(0), // disable adaptive scheduling by default + iRefreshLoopPriority(CActive::EPriorityStandard), + iRefreshLoopActive(EFalse) + { + iIdleCPUValueMonitored = CPUTimeSupported() && OpenHandleToIdleCPUValueThread(); + } + +// to get around nasty ownership problem with texture manager interface +void NullTextureManagerPtr(TAny* aPtrToPtr) + { + if (aPtrToPtr) + { + CHuiTextureManager** ptr = (CHuiTextureManager**)aPtrToPtr; + *ptr = 0; + } + } + +void CHuiEnv::ConstructL(THuiRenderer aRenderer) + { + HUI_DEBUG(_L("CHuiEnv::ConstructL() - Constructing Hitchcock User Interface Toolkit (HUITK) working environment") ); + HUI_DEBUG1(_L("CHuiEnv::ConstructL() - Free memory in beginning: %i"), HuiUtil::FreeMemory()); + + // Static data area. + iStatic = CHuiStatic::NewL(this); + HUI_DEBUG1(_L("CHuiEnv::ConstructL() - Free memory after static created: %i"), HuiUtil::FreeMemory()); + + // Instantiate the right type of renderer plugin. + + + // The Ecom plugin framework requires the identifier to be a descriptor. + // Convert the identifier to descriptor, which the ecom uses to determine + // the correct renderer. + + // -----------RnD------------------------------------------------------------- + // Disable renderer selection for now !! + // -----------RnD------------------------------------------------------------- + + // can't currently switch on fly and alf_config has its issues.. + aRenderer = EHuiRendererVg10; + + + TBuf<10> renderer; + renderer.Num(aRenderer); + + // The aRenderer holds the renderer information which is usually gotten from + // central repository key. It might not be defined though, and in that case, + // we'll try to load from the + switch(aRenderer) + { + case EHuiRendererDefault: + { + const THuiRenderer rendererTable[] = + { + EHuiRendererVg10, + EHuiRendererBitgdi, + EHuiRendererGles20, + EHuiRendererGles11, + EHuiRendererGles10, + }; + const TInt KRendererCount = 5; + for (TInt index = 0; index < KRendererCount ; index++) + { + renderer.Num(rendererTable[index]); + TRAPD(error, iRenderer = reinterpret_cast(CHuiRenderPluginBase::NewL( renderer ))); + if (error) + { + HUI_DEBUG1(_L("CHuiEnv::ConstructL() - Renderer construction failed, error code: %i, trying next one...."),error ); + if (index == KRendererCount-1) + { + // the last renderer in the table failed to load + HUI_DEBUG(_L("CHuiEnv::ConstructL() - ERROR! Failed to create any renderer.. bailing out") ); + User::Leave(error); + } + continue; + } + // got a renderer, use that... + iRendererIdentifier = rendererTable[index]; + break; + } + break; + } + + + default: + { + // Load the renderer plugin with the given identifier. The Ecom framework + // will take care searching for matching renderer. If not found, will leave with KErrNotFound + iRenderer = reinterpret_cast(CHuiRenderPluginBase::NewL( renderer )); + iRendererIdentifier = aRenderer; + + // @TODO Should we panic, if renderer wasn't found, or is the Leave + // with KErrNotFound enough? + //THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer); + break; + } + } + + iStatic->SetRenderer(*iRenderer); + + CHuiStatic::Tic(1); + + // Create the scheduler. + iScheduler = new (ELeave) CHuiScheduler(*this); + + // Create a texture manager. + + CleanupStack::PushL(TCleanupItem(NullTextureManagerPtr,&iTextureManager)); + iTextureManager = iRenderer->CreateTextureManagerL(*this); + // Register as a state change and texture loaded event observer + CleanupStack::Pop(); + iTextureManager->iStateObservers.AppendL(*this); + iTextureManager->iLoadObservers.AppendL(*this); + + // Create a font manager. + iFontManager = iRenderer->CreateFontManagerL(); + + // Create a text style manager. + iTextStyleManager = CHuiTextStyleManager::NewL(); + iTextStyleManager->ConstructBuiltInStylesL(); + + // Create a visual factory. + iVisualFactory = new (ELeave) CHuiVisualFactory(*this); + + // Create an effects engine + iEffectsEngine = iRenderer->CreateEffectsEngineL(); + + // Cache the last input time. + iLastInputTime = CHuiStatic::Time(); + + // Create a shared roster. This is used by all overlaid displays. + iSharedRoster = new (ELeave) CHuiRosterImpl(NULL); + + /** @todo Create a skin here. This must be done in a better way. + The skin can only be created when there is a EGL context because + the skin will attempt to create textures and load fonts. */ + + if(!iSkin) + { + if(iEnvObserver) + { + iSkin = iEnvObserver->CreateSkinL(*this); + } + if(!iSkin) + { + // Create an instance of the default skin. The S60 skin uses data + // and bitmaps from the current S60 skin. + iSkin = new (ELeave) CHuiS60Skin(*this); + (static_cast(iSkin))->ConstructL(); + } + } + + // DEPRECATED: JUST A DUMMY CONSTRUCTION TO PREVENT BREAKS + //iThemeManager = CHuiThemeManager::NewL(); + + iCanvasTextureCache = CHuiCanvasTextureCache::NewL(); + +#ifndef SYMBIAN_BUILD_GCE +#ifndef __WINSCW__ + // for now, display fps information automatically if errrd installed + if (eikenv) + { + _LIT(KRDSupport, "c:\\resource\\errrd" ); + if (eikenv->FsSession().Handle() && BaflUtils::FileExists( eikenv->FsSession(), KRDSupport )) + { + SetFPSCounterThreshold(700); + } + } +#endif +#endif //SYMBIAN_BUILD_GCE + HUI_DEBUG(_L("CHuiEnv::ConstructL - Working environment ready.")); + } + + +CHuiEnv::~CHuiEnv() + { + iActionObservers.Close(); + + // Destroy groups in reverse order so that references will be removed + // in natural order. + TInt i = 0; + for(i = iLoadedGroups.Count() - 1; i >= 0; --i) + { + CHuiControlGroup* g = iLoadedGroups[i]; + iLoadedGroups.Remove(i); + delete g; + } + iLoadedGroups.Reset(); + + for(i = iDisplays.Count() - 1; i >= 0; --i) + { + // Deleting a display causes it to be automatically removed from the + // displays array. + delete iDisplays[i]; + } + + iDisplays.Reset(); + iOverlaidDisplays.Reset(); + + delete iCanvasTextureCache; + + delete iSharedRoster; + delete iSkin; + delete iVisualFactory; + delete iTextureManager; + delete iEffectsEngine; + + // DEPRECATED: JUST A DUMMY DESTRUCTION + //delete iThemeManager; //Theme support + + delete iFontManager; + delete iTextStyleManager; + delete iPeriodic; + delete iScheduler; + iScheduler = NULL; + delete iRenderer; + delete iStatic; + iEnvObserver = NULL; + + if (iIdleCPUValueMonitored) + { + CloseHandleToIdleCPUValueThread(); + } + + iLowMemoryObservers.Close(); + iMemoryLevelObservers.Close(); + } + + +void CHuiEnv::SetTextureManager(CHuiTextureManager& aManager) + { + iTextureManager = &aManager; + } + + +EXPORT_C THuiRenderer CHuiEnv::Renderer() const + { + return iRendererIdentifier; + } + + +EXPORT_C void CHuiEnv::SetRefreshMode(THuiRefreshMode aMode) + { + switch (aMode) + { + case EHuiRefreshModeManual: + //HUI_DEBUG(_L("CHuiEnv::SetRefreshMode() - Setting manual refresh mode.")); + break; + case EHuiRefreshModeAutomatic: + //HUI_DEBUG(_L("CHuiEnv::SetRefreshMode() - Setting automatic refresh mode.")); + break; + case EHuiRefreshModeForced: + //HUI_DEBUG(_L("CHuiEnv::SetRefreshMode() - Setting forced refresh mode.")); + break; + default: + //HUI_DEBUG(_L("CHuiEnv::SetRefreshMode() - ERROR! Tried to set unknown refresh mode! Ignoring..")); + return; + } + + +#ifdef HUI_NGA_FORCED_REFRESH + iRefreshMode = EHuiRefreshModeForced; +#else + iRefreshMode = aMode; +#endif + + if(aMode == EHuiRefreshModeManual) + { + StopRefresh(); + } + else + { + StartRefresh(iRefreshIntervalTarget); + } + } + + +EXPORT_C THuiRefreshMode CHuiEnv::RefreshMode() const + { + return iRefreshMode; + } + + +EXPORT_C void CHuiEnv::SetMaxFrameRate(TReal32 aFrameRate) __SOFTFP + { +#ifdef HUI_NGA_MIN_REFRESH_INTERVAL + if (aFrameRate < (1000/KHuiEnvDefaultNormalRefreshIntervalMs)) + aFrameRate = 1000/KHuiEnvDefaultNormalRefreshIntervalMs; +#endif + + TInt oldIRefreshIntervalTarget = iRefreshIntervalTarget; + if(aFrameRate != 0.0) + { + iRefreshIntervalTarget = TInt(1000 / aFrameRate); + } + else + { + iRefreshIntervalTarget = KHuiEnvDefaultNormalRefreshIntervalMs; + } + + if(iRefreshIntervalTarget < 1) + { + iRefreshIntervalTarget = 1; + } + + // If the refresh timer is running, update it. + if(!iMaxCPUUtilization && /* Adaptive scheduling not enabled */ + iPeriodic && (iPeriodic->IsActive() || iRefreshLoopActive ) && /* and heart beat already active */ + oldIRefreshIntervalTarget != iRefreshIntervalTarget ) + { + StartRefresh(iRefreshIntervalTarget); + } + } + + +EXPORT_C void CHuiEnv::StartRefresh(TInt aMilliSeconds) + { + StartRefresh(aMilliSeconds, aMilliSeconds); + } + +void CHuiEnv::StartRefresh(TInt aIntervalInMilliSeconds, TInt aDelayInMilliseconds) + { + // Cancel the previous timer. + StopRefresh(); + + if(iState == EReleased) + { + // When environment is released no refresh is done. + return; + } + + if ( aIntervalInMilliSeconds < 1 ) + { + HUI_DEBUG1(_L("CHuiEnv::StartRefresh() - Requested %i ms - too low!."), aIntervalInMilliSeconds); + aIntervalInMilliSeconds = 1; + } + + if (aIntervalInMilliSeconds > 1000) + { + HUI_DEBUG1(_L("CHuiEnv::StartRefresh() - Requested %i ms - too high!."), aIntervalInMilliSeconds); + aIntervalInMilliSeconds = 1000; + } + + if ( aDelayInMilliseconds < 1 ) + { + HUI_DEBUG1(_L("CHuiEnv::StartRefresh() - Requested %i aDelayInMilliseconds ms - too low!."), aDelayInMilliseconds); + aDelayInMilliseconds = 1; + } + + if (aDelayInMilliseconds > 1000) + { + HUI_DEBUG1(_L("CHuiEnv::StartRefresh() - Requested %i aDelayInMilliseconds ms - too high!."), aDelayInMilliseconds); + aDelayInMilliseconds = 1000; + } + + + //HUI_DEBUG1(_L("CHuiEnv::StartRefresh() - Starting at %i ms interval."), aMilliSeconds); + + // Create a new refresh timer. + + TInt err(0); + if (!iPeriodic) + { +#ifdef HUI_HIRES_TIMER + TRAP(err, iPeriodic = CHighResTimer::NewL(TCallBack(CHuiEnv::RefreshCallBack, this), iRefreshLoopPriority)); +#else + TRAP( err, iPeriodic = CPeriodic::NewL(iRefreshLoopPriority) ); +#endif + } + + if (!err) + { +#ifdef HUI_HIRES_TIMER + iPeriodic->CallBack( aIntervalInMilliSeconds ); +#else + iPeriodic->Start(TTimeIntervalMicroSeconds32(1000 * aDelayInMilliseconds), + TTimeIntervalMicroSeconds32(1000 * aIntervalInMilliSeconds), + TCallBack(CHuiEnv::RefreshCallBack, this)); +#endif + iRefreshLoopActive = ETrue; + + // Store current refresh interval + iRefreshInterval = aIntervalInMilliSeconds; + } + } + +void CHuiEnv::StopRefresh() + { + //HUI_DEBUG(_L("CHuiEnv::StopRefresh()")); + if(iPeriodic) + { + iPeriodic->Cancel(); + iRefreshLoopActive = EFalse; + } + } + + +EXPORT_C void CHuiEnv::ContinueRefresh() + { + ContinueRefresh(EFalse); + } + +void CHuiEnv::ContinueRefresh(TBool aFastFirstRefresh) + { + if((iRefreshMode == EHuiRefreshModeManual) || + (iState == EReleased)) + { + // When running in manual refresh mode, this has no effect. Refreshes + // must be manually requested. + // When environment is released no refresh is done. + return; + } + + if(!iPeriodic || ( !iPeriodic->IsActive() && !iRefreshLoopActive ) ) + { + HUI_DEBUG1(_L("CHuiEnv::ContinueRefresh() - Continuing normal refresh with %i ms intervals."), + iRefreshInterval); + + TInt refreshDelay = aFastFirstRefresh ? 1 : iRefreshIntervalTarget; + StartRefresh(iRefreshIntervalTarget, refreshDelay); + + // When refresh is paused, the frame rate is virtually infinite + // since nothing needs to be done on each refresh. This means that + // when refresh continues, the first elapsed step should be zero. + // A call to UpdateTime() updates the internal absolute clock with + // the latest time. + CHuiStatic::UpdateTime(); + } + } + +EXPORT_C void CHuiEnv::PauseRefresh() + { + HUI_DEBUG(_L("CHuiEnv::PauseRefresh() - Refresh paused due to inactivity.")); + HUI_DEBUG1(_L("CHuiEnv::PauseRefresh() - Free memory left: %i"), HuiUtil::FreeMemory()); + StopRefresh(); + } + + +EXPORT_C CHuiDisplay& +CHuiEnv::NewDisplayL(const TRect& aRect, CCoeControl* aNativeControl, TInt aFlags, + CHuiDisplay* aDisplayToShareRoster, TInt aDisplayType ) + { + return NewDisplayL(aRect, aNativeControl, aFlags, aDisplayToShareRoster, aDisplayType, KHuiUidBackBufferScreen0); + } + + +EXPORT_C CHuiDisplay& +CHuiEnv::NewDisplayL(const TRect& aRect, CCoeControl* aNativeControl, TInt aFlags, + CHuiDisplay* aDisplayToShareRoster, TInt aDisplayType, TUid aBackBufferUid) + { + TBool isDisplayTypeTvOut = + ((aDisplayType == CHuiDisplay::EDisplayTvOut) || + (aDisplayType == CHuiDisplay::EDisplayTvOutWide) || + ((aDisplayType == CHuiDisplay::EDisplayNormal) && + ((aBackBufferUid == KHuiUidBackBufferTvOutNormal) || + (aBackBufferUid == KHuiUidBackBufferTvOutWide)))); + + if ((iRendererIdentifier != EHuiRendererBitgdi) && + (isDisplayTypeTvOut || (aDisplayType == CHuiDisplay::EDisplayOffScreenBuffer))) + { + User::Leave(KErrNotSupported); + } + + CHuiRoster* roster = NULL; + if (aDisplayToShareRoster) + { + roster = &aDisplayToShareRoster->Roster(); + } + if(aFlags & ENewDisplayOverlaid) + { + roster = iSharedRoster; + } + + CHuiDisplay* display = new (ELeave) CHuiDisplay(*this, aNativeControl, aDisplayType, aBackBufferUid); + CleanupStack::PushL(display); + display->ConstructL(aRect, roster); + User::LeaveIfError(iDisplays.Append(display)); + CleanupStack::Pop(display); + + // Notify the current renderer of the changed number of displays + iRenderer->NotifyDisplayCountL(iDisplays.Count()); + + HUI_DEBUG2(_L("HuiEnv::NewDisplay %x added to array, with flags %x"), display, aFlags); + + // Notify observers about new TvOut display + if(isDisplayTypeTvOut) + { + ReportAction(THuiActionCommand(KHuiActionNewTVOutDisplayUid.iUid)); + } + + return *display; + } + +EXPORT_C CHuiDisplay& CHuiEnv::NewDisplayL(RWindow* aNativeWindow, + TInt aFlags, + CHuiDisplay* aDisplayToShareRoster, + TInt aDisplayType, + TUid aBackBufferUid) + { + CHuiRoster* roster = NULL; + if (aDisplayToShareRoster) + { + roster = &aDisplayToShareRoster->Roster(); + } + if(aFlags & ENewDisplayOverlaid) + { + roster = iSharedRoster; + } + + CHuiDisplay* display = new (ELeave) CHuiDisplay(*this, aNativeWindow, aDisplayType, aBackBufferUid); + CleanupStack::PushL(display); + display->ConstructL(TRect(TPoint(0,0),aNativeWindow->Size()), roster); + User::LeaveIfError(iDisplays.Append(display)); + CleanupStack::Pop(display); + + // Notify the current renderer of the changed number of displays + iRenderer->NotifyDisplayCountL(iDisplays.Count()); + + HUI_DEBUG2(_L("HuiEnv::NewDisplay %x added to array, with flags %x"), display, aFlags); + + return *display; + } + + +EXPORT_C TInt CHuiEnv::DisplayCount() const + { + return iDisplays.Count(); + } + + +void CHuiEnv::RemoveDisplay(CHuiDisplay& aDisplay) + { + // Actually this is "DestroyDisplay" + + /** @todo Make a proper observer. */ + TInt index = iDisplays.Find(&aDisplay); + if(index >= 0) + { + iDisplays.Remove(index); + } + else + { + HUI_DEBUG1(_L("HuiEnv::DestroyContext: display %x not in array"), &aDisplay); + } + index = iOverlaidDisplays.Find(&aDisplay); + if(index >= 0) + { + iOverlaidDisplays.Remove(index); + } + + // Notify the current renderer of the changed number of displays + TRAP_IGNORE(iRenderer->NotifyDisplayCountL(iDisplays.Count())) + +#ifdef _DEBUG + HUI_DEBUG(_L(" Contents of iDisplays:")); + for(TInt i = 0; i < iDisplays.Count(); ++i) + { + HUI_DEBUG2(_L(" %i: %x"), i, iDisplays[i]); + } +#endif + } + + +EXPORT_C TInt CHuiEnv::RefreshCallBack(TAny* aInstance) + { + ASSERT( aInstance ); + CHuiEnv* self = static_cast( aInstance ); + + TReal32 elapsedTime = 0; + + // Investigate whether the environment is released + if(self->iState == EReleased) + { + HUI_DEBUG(_L("CHuiEnv::RefreshCallBack() - Warning: Refresh callback called while environment is released.")); + return KErrNone; + } + + self->SetTimeFromLastUpdate(CHuiStatic::MilliSecondsSinceUpdateTime()); + // Compute the elapsed time (in sec.) between the current and the + // previous refresh call. + CHuiStatic::UpdateTime(); + elapsedTime = CHuiStatic::ElapsedSeconds(); + + // Time advancements should not happen in too large increments. + /** @todo The time advancement should be done in steps if the + elapsed time is too long. The static time in CHuiStatic + should also be updated using the same steps. This will + allow scheduled commands to be executed and timed + correctly (start times of timed transitions). */ + + HUI_DEBUGF1(_L("CHuiEnv::RefreshCallBack() - Elapsed time: %f"), elapsedTime); + + if (elapsedTime < 0) + { + elapsedTime = 1; + } + + self->AdvanceTime(elapsedTime); + + // Report the current frame rate at certain intervals. + TReal32 nowTime = CHuiStatic::SecondsSinceStart(); + if(nowTime - self->iPreviousFpsTime > 3) + { + HUI_DEBUG1(_L("CHuiEnv::RefreshCallBack() - FPS: %f"), CHuiStatic::FrameRate()); + self->iPreviousFpsTime = nowTime; + } + + return KErrNone; + } + + +void CHuiEnv::AdvanceTime(TReal32 aElapsedTime) + { + HUI_DEBUGF( _L("CHuiEnv::AdvanceTime() - Started") ); +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + TTime startTime; + TTime endTime; +#endif + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L("CHuiEnv::AdvanceTime starting measuring 0.")); + startTime.UniversalTime(); +#endif + + + TUint usedMaxCPUUtilization = iMaxCPUUtilization; + + // Calculate cpu values based on null thread cpu usage between frames. + // Values will be updated at the end of the frame. + if (iIdleCPUValueMonitored && usedMaxCPUUtilization) + { + TTime currentTime; + currentTime.HomeTime(); + + TTimeIntervalMicroSeconds cputime; + iIdleCPUValueThread.GetCpuTime(cputime); + + TInt64 cpudelta = cputime.Int64() - iIdleCPUValue; + TInt64 timedelta = currentTime.Int64() - iIdleCPUValuePreviousTime; + + // If null thread was runnign between frames, we could use more cpu if needed. + if (cpudelta && timedelta) + { + // Calculate how much we want ! + if (iMaxCPUUtilization > KHuiEnvMaxCpuTimeOverdriveLowerThreshold && + iMaxCPUUtilization < KHuiEnvMaxCpuTimeOverdriveMaxValue ) + { + usedMaxCPUUtilization += (KHuiEnvMaxCpuTimeOverdriveMaxValue - iMaxCPUUtilization) * cpudelta/timedelta; + + // Sanity check just in case cpu/time measurements are not accurate + if (usedMaxCPUUtilization > KHuiEnvMaxCpuTimeOverdriveMaxValue) + { + usedMaxCPUUtilization = KHuiEnvMaxCpuTimeOverdriveMaxValue; + } + + if (usedMaxCPUUtilization < iMaxCPUUtilization) + { + usedMaxCPUUtilization = iMaxCPUUtilization; + } + } + } + } + + if(aElapsedTime > 0) + { + // Let the scheduler know that time has passed. It will possible animate + // visuals and perform actions, causing dirty regions in the display. + iScheduler->AdvanceTime(aElapsedTime); + + // Scheduled command might have released the environment. + if(iState == EReleased) + { + HUI_DEBUG(_L("CHuiEnv::AdvanceTime() - Environment released when executing scheduled commands. AdvanceTime cancelled.")); + return; + } + + // Let the texture manager know that time has passed. It will update any + // animated textures. + iTextureManager->AdvanceTime(aElapsedTime); + // Notify the effects engine to update animated effects + if (iEffectsEngine) + { + iEffectsEngine->AdvanceTime(aElapsedTime); + + // Notify the effects end observers + iEffectsEngine->NotifyEffectEndObservers(); + } + } + + // Check for no input for long time. + TTime now = CHuiStatic::Time(); + TTimeIntervalSeconds seconds = 0; + now.SecondsFrom(iLastInputTime, seconds); + if(seconds.Int() >= iIdleThreshold && !iInputIdleIsActive) + { + HUI_DEBUG1(_L("CHuiEnv::AdvanceTime() - No input received within %i seconds. Going to idle."), iIdleThreshold); + iInputIdleIsActive = ETrue; + + // Idle state begins. + TRAPD(err, SendIdleL(ETrue)); + if(err != KErrNone) + { + // @todo Log error? + } + + // Switching to idle state might have released the environment. + if(iState == EReleased) + { + HUI_DEBUG(_L("CHuiEnv::AdvanceTime() - Environment released when switching to idle state. AdvanceTime cancelled.")); + return; + } + } + + TBool somethingUpdated = EFalse; + + // Refresh all displays. + TInt i; + const TInt displayCount = iDisplays.Count(); + RArray displayRefreshed( displayCount ? displayCount : 1 ); + for(i = 0; i < iDisplays.Count(); ++i) + { + displayRefreshed.Append(EFalse); + if(iRefreshMode == EHuiRefreshModeForced || iDisplays[i]->IsDirty()) + { + MakeCurrent(*iDisplays[i]); + + HUI_DEBUGF1( _L("CHuiEnv::AdvanceTime() - Refreshing display %i"), i ); + TBool updated = iDisplays[i]->Refresh(); + displayRefreshed[i] = updated; + if(updated) + { + somethingUpdated = ETrue; + } + } + } + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + endTime.UniversalTime(); + TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L("CHuiEnv::AdvanceTime first part %i ms"), timeInMs); +#endif + + TBool continueRefresh = ETrue; + + if(somethingUpdated) + { + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L("CHuiEnv::AdvanceTime starting measuring 2.")); + startTime.UniversalTime(); +#endif + + iIdleRefreshCount = 0; + // Clear change flags now that the frames are complete. + for(i = 0; i < iDisplays.Count(); ++i) + { + // Clear changed for an off screen display only if the buffer has new content. + // Index is ok becacause displayRefreshed array was defined using size of iDisplays array + if (displayRefreshed[i]) + { + iDisplays[i]->ClearChanged(); + } + } + } + else if(iScheduler->PendingCount() == 0) + { + // But if there are scheduled commands, let's make sure they'll get + // executed at the right time. They might get badly delayed if the + // refresh wasn't occuring. + + /** @todo Use a separate timer for the scheduler? */ + + // Nothing happened during the display refreshing. + iIdleRefreshCount++; + + // If this occurs too often, pause refresh automatically. + if(iIdleRefreshCount > KIdleRefreshCountThreshold) + { + if (iFpsCounterThreshold && iMillisecondFromFPSUpdate && iFrames) + { + TBuf<16> numBuf; + TReal fps = 1000*(TReal)iFrames/iMillisecondFromFPSUpdate; + numBuf.AppendNum(fps, TRealFormat(5,2)); + User::InfoPrint(numBuf); + iFrames = 0; + iMillisecondFromFPSUpdate = 0; + } + + PauseRefresh(); + continueRefresh = EFalse; + } + } + else + { + // for PC lint + } + + if(somethingUpdated) + { + HUI_DEBUGF( _L("CHuiEnv::AdvanceTime() - Swap buffers") ); + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L("CHuiEnv::AdvanceTime starting measuring 1.")); + startTime.UniversalTime(); +#endif + + SwapBuffers(displayRefreshed); + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + endTime.UniversalTime(); + TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L("CHuiEnv::AdvanceTime swapbuffers took %i ms"), timeInMs); +#endif + } + + displayRefreshed.Close(); // Not needed any more + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + endTime.UniversalTime(); + timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L("CHuiEnv::AdvanceTime iDisplays[i]->ClearChanged() took %i ms"), timeInMs); +#endif + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L("CHuiEnv::AdvanceTime starting measuring 3.")); + startTime.UniversalTime(); +#endif + + + // Clear change flags of all control groups now that the refresh has + // been completed for all displays. + // + // DEPRECATE: + // This should be removed when control opacities are deprecated! + // Controls shouldn't need change flags because change flags are + // only for the refresh. + // + for(i = 0; i < iLoadedGroups.Count(); ++i) + { + iLoadedGroups[i]->ClearChanged(); + } + + iTextureManager->ClearChangedTextures(); + iCanvasTextureCache->AdvanceTime(); + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + endTime.UniversalTime(); + timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L("CHuiEnv::AdvanceTime textures ClearChanged() and other stuff took %i ms"), timeInMs); +#endif + + if (continueRefresh) + { + TUint refreshTime = CHuiStatic::MilliSecondsSinceUpdateTime(); + // Refresh rate adjustment + if (usedMaxCPUUtilization) + { + // Estimated frame, when sleep time is included. + TUint estimatedTotalRefreshTime = (refreshTime * 100) / usedMaxCPUUtilization; + + if (estimatedTotalRefreshTime >= iRefreshIntervalTarget) + { + // Rendering slower that fps limit set by user. + // Start refresh after the sleep period as the frame has already been rendered. + StartRefresh(estimatedTotalRefreshTime - refreshTime); + } +#ifndef HUI_HIRES_TIMER + else if (iRefreshIntervalTarget != iRefreshInterval) + { + StartRefresh(iRefreshIntervalTarget); + } +#endif + else + { + // Rendering faster than the fps limit set by user. Limit fps to target fps. + // The sleep time is the full frame time less by the render time. +#ifdef HUI_HIRES_TIMER + StartRefresh( iRefreshIntervalTarget - refreshTime ); +#endif + } + } + else + { + // No CPU utilisation. + // The sleep time is the full frame time less by the render time. +#ifdef HUI_HIRES_TIMER + StartRefresh( iRefreshIntervalTarget - refreshTime ); +#endif + } + + if (iFpsCounterThreshold && iMillisecondFromFPSUpdate > iFpsCounterThreshold) + { + TBuf<16> numBuf; + TReal fps = 1000*(TReal)iFrames/iMillisecondFromFPSUpdate; + numBuf.AppendNum(fps, TRealFormat(5,2)); + User::InfoPrint(numBuf); + iFrames = 0; + iMillisecondFromFPSUpdate = 0; + } + } + + iCurrentDisplay = NULL; // informs the egosystem that the drawing is done. + CHuiStatic::ReportNewFrame(); + + // Store cpu value conters of null thread. Values will be used at the start of the next frame. + if (iIdleCPUValueMonitored) + { + TTime currentTime; + currentTime.HomeTime(); + + TTimeIntervalMicroSeconds cputime; + iIdleCPUValueThread.GetCpuTime(cputime); + + // Store as previous values + iIdleCPUValue = cputime.Int64(); + iIdleCPUValuePreviousTime = currentTime.Int64(); + } + + HUI_DEBUGF( _L("CHuiEnv::AdvanceTime() - Exited") ); + } + + +EXPORT_C TBool CHuiEnv::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType, + CHuiDisplay* aAssocDisplay) + { + if(aAssocDisplay) + { + THuiEvent event(aAssocDisplay, aKeyEvent, aType); + + // Notify the environment itself. + NotifyInputReceivedL(event); + + if(aAssocDisplay->Roster().HandleEventL(event)) + { + return EKeyWasConsumed; + } + return EKeyWasNotConsumed; + } + + return EKeyWasNotConsumed; + } + + +void CHuiEnv::NotifyInputReceivedL(const THuiEvent& aEvent) + { + ContinueRefresh(); + + if(aEvent.IsKeyEvent() || aEvent.IsPointerEvent()) + { + if(iInputIdleIsActive) + { + HUI_DEBUG(_L("CHuiEnv::NotifyInputReceivedL() - Got key/pointer input! Idle state ends!")); + // Idle state ends. + SendIdleL(EFalse); + } + + iLastInputTime = CHuiStatic::Time(); + iInputIdleIsActive = EFalse; + } + } + + +void CHuiEnv::SendIdleL(TBool aIdleBegins) + { + CHuiDisplay* display = NULL; + + if(iDisplays.Count() != 0) + { + // If we have any displays, pass the first one. + display = iDisplays[0]; + } + + THuiEvent idleEvent(display, + aIdleBegins ? THuiEvent::ETypeIdleBegin : + THuiEvent::ETypeIdleEnd); + BroadcastEventL(idleEvent); + } + + +EXPORT_C void CHuiEnv::SetIdleThreshold(TInt aMilliSeconds) + { + iIdleThreshold = aMilliSeconds/1000; + } + + +EXPORT_C void CHuiEnv::BroadcastEventL(const THuiEvent& aEvent) + { + for(TInt i = 0; i < iDisplays.Count(); ++i) + { + THuiEvent event = aEvent; + event.iDisplay = iDisplays[i]; + /** @todo Musn't access the roster directly. */ + iDisplays[i]->Roster().HandleEventL(event); + } + } + + +void CHuiEnv::MakeCurrent(const CHuiDisplay& aDisplay) const + { + aDisplay.RenderSurface().MakeCurrent(); + iCurrentDisplay = const_cast(&aDisplay); + } + + +void CHuiEnv::SwapBuffers(const RArray& aDisplayRefreshed) + { + /** @todo This may not work as expected when multiple displays are + being used. */ + + if (iFpsCounterThreshold) + { + iFrames++; + iMillisecondFromFPSUpdate += iRefreshIntervalReal; + } + + /** @todo Only swap the visible displays. */ + + for(TInt i = 0; i < iDisplays.Count(); ++i) + { + // Index should ok becacause displayRefreshed array was defined using size of iDisplays array + // This function should only be called from inside CHuiEnv even if it is public. + // At least it is not exported. + if (aDisplayRefreshed[i] + && (iDisplays[i]->DisplayType() != CHuiDisplay::EDisplayOffScreenBuffer) + && (iDisplays[i]->ScreenBufferObserver() == NULL)) + { + MakeCurrent(*iDisplays[i]); + if (iSwapObserver) + iSwapObserver->PrepareSwap(); + iDisplays[i]->RenderSurface().SwapBuffers(); + if (iSwapObserver) + iSwapObserver->SwapComplete(); + + } + } + } + + +void CHuiEnv::CreateResourceReaderLC(TResourceReader& aReader, TInt aResourceId) const + { + CCoeEnv* coe = CCoeEnv::Static(); + if (!coe) + { + User::Leave(KErrNotSupported); + } + coe->CreateResourceReaderLC(aReader, aResourceId); + } + + +EXPORT_C CHuiControlGroup& CHuiEnv::NewControlGroupL(TInt aId) + { + CHuiControlGroup* group = new (ELeave) CHuiControlGroup(aId, *this); + CleanupStack::PushL(group); + User::LeaveIfError(iLoadedGroups.Append(group)); + CleanupStack::Pop(group); + return *group; + } + + +EXPORT_C TInt CHuiEnv::DeleteControlGroup(TInt aId) + { + TInt i; + + for(i = 0; i < iLoadedGroups.Count(); ++i) + { + if(iLoadedGroups[i]->ResourceId() == aId) + { + // This is control group to delete. + CHuiControlGroup* group = iLoadedGroups[i]; + CancelCommands(group); + + for (TInt ii = iDisplays.Count()-1; ii>=0; ii--) + { + TInt index = iDisplays[ii]->Roster().Find(group); + if (index != KErrNotFound) + { + iDisplays[ii]->Roster().Hide(iDisplays[ii]->Roster().ControlGroup(index)); + } + } + + iLoadedGroups.Remove(i); + delete group; + return KErrNone; + } + } + + return KErrNotFound; + } + + +EXPORT_C CHuiControlGroup& CHuiEnv::LoadControlGroupL(TInt aResourceId) + { + CHuiControlGroup* group = new (ELeave) CHuiControlGroup(aResourceId, *this); + CleanupStack::PushL(group); + + // Create a resource reader and construct the group and its controls. + TResourceReader reader; + CreateResourceReaderLC(reader, aResourceId); + group->ConstructFromResourceL(reader); + CleanupStack::PopAndDestroy(); // reader + + // Add the control group to the list of all existing groups. + // The environment will retain ownership of the group. + User::LeaveIfError( iLoadedGroups.Append(group) ); + + CleanupStack::Pop(group); + return *group; + } + + +EXPORT_C void CHuiEnv::LoadBitmapsL(TInt aResourceId) + { + TResourceReader reader; + CreateResourceReaderLC(reader, aResourceId); + + TInt count = reader.ReadInt16(); + HUI_DEBUG2(_L("CHuiEnv::LoadBitmapsL() - Registering %i bitmaps from resource id %i to the texture manager."), count, aResourceId); + + TInt i = 0; + CHuiTextureManager & manager = TextureManager(); + for(i = 0; i < count; ++i) + { + TInt id = reader.ReadInt32(); + TPtrC fileName = reader.ReadTPtrC(); + HUI_DEBUG2(_L("CHuiEnv::LoadBitmapsL() - Bitmap id %i: \"%S\""), id, &fileName); + manager.DefineFileNameL(id, fileName); + } + + CleanupStack::PopAndDestroy(); // reader + } + + +EXPORT_C CHuiControlGroup& CHuiEnv::ControlGroup(TInt aResourceId) + { + for(TInt i = 0; i < iLoadedGroups.Count(); ++i) + { + if(iLoadedGroups[i]->ResourceId() == aResourceId) + { + return *iLoadedGroups[i]; + } + } + + // Group hasn't been loaded yet + /** @todo load automatically? */ + THuiPanic::Panic(THuiPanic::EInternal); + return *iLoadedGroups[0]; + } + + +EXPORT_C CHuiControl* CHuiEnv::FindControl(TInt aId) const + { + for(TInt i = 0; i < iLoadedGroups.Count(); ++i) + { + CHuiControl* control = iLoadedGroups[i]->FindControl(aId); + if(control) + { + return control; + } + } + // The control does not exist. + return NULL; + } + + +EXPORT_C CHuiVisualFactory& CHuiEnv::VisualFactory() const + { + return *iVisualFactory; + } + + +EXPORT_C CHuiTextureManager& CHuiEnv::TextureManager() const + { + return *iTextureManager; + } + + +EXPORT_C THuiFontManager& CHuiEnv::FontManager() const + { + return *iFontManager; + } + + +EXPORT_C CHuiTextStyleManager& CHuiEnv::TextStyleManager() const + { + return *iTextStyleManager; + } + + +EXPORT_C CHuiSkin& CHuiEnv::Skin() const + { + return *iSkin; + } + + +EXPORT_C void CHuiEnv::NotifySkinChangedL() + { + ReportAction(THuiActionCommand(KAknsMessageSkinChange)); + for(TInt i = 0; i < iDisplays.Count(); ++i) + { + iDisplays[i]->RosterImpl().NotifySkinChangedL(); + } + iTextureManager->NotifySkinChangedL(); + } + + +EXPORT_C TInt CHuiEnv::Send(const THuiCommand& aCommand, TInt aDelayMilliSeconds) + { + TRAPD(err, SendL(aCommand, aDelayMilliSeconds)); + if(err != KErrNone) + { + HUI_DEBUG1(_L("CHuiEnv::Send() - Leave %i while posting command."), err); + } + return err; + } + + +EXPORT_C void CHuiEnv::SendL(const THuiCommand& aCommand, TInt aDelayMilliSeconds) + { + ContinueRefresh(); + iScheduler->PostCommandL(aCommand, aDelayMilliSeconds); + } + + +EXPORT_C void CHuiEnv::CancelCommands(TAny* aObject) + { + if (iScheduler) + { + iScheduler->CancelCommands(aObject); + } + } + + +EXPORT_C void CHuiEnv::CancelCommands(MHuiEventHandler* aObject) + { + if (iScheduler) + { + iScheduler->CancelCommands(aObject); + } + } + + +EXPORT_C void CHuiEnv::CancelCommands(TAny* aObject, + THuiOp aCommandOperation) + { + if (iScheduler) + { + iScheduler->CancelCommands(aObject, aCommandOperation); + } + } + + +EXPORT_C void CHuiEnv::CancelCommands(TAny* aObject, + THuiCommandType aCommandType, + TInt aParam) + { + if (iScheduler) + { + iScheduler->CancelCommands(aObject, aCommandType, aParam); + } + } + + +EXPORT_C TInt CHuiEnv::TimeUntilCommand(TAny* aObject, + THuiCommandType aCommandType) + { + return iScheduler->TimeUntilCommand(aObject, aCommandType); + } + + +void CHuiEnv::TextureLoadingCompleted(CHuiTexture& /*aTexture*/, + TInt /*aTextureId*/, + TInt /*aErrorCode*/) + { + // Texture changed flag has been set, visuals should redraw + // changed textures automatically. + } + + +void CHuiEnv::TextureManagerStateChanged(const CHuiTextureManager& aManager) + { + if(aManager.State() == CHuiTextureManager::EIdle) + { + StartRefresh(iRefreshIntervalTarget); + } + else if (!iMaxCPUUtilization) + { // only use busy refresh interwall if adaptive scheduling is not enabled + StartRefresh(KHuiEnvDefaultBusyRefreshIntervalMs); + } + else + { + // for PC lint + } + } + + +EXPORT_C CHuiDisplay& CHuiEnv::PrimaryDisplay() const + { + return *iDisplays[0]; + } + + +EXPORT_C CHuiDisplay& CHuiEnv::Display(TInt aIndex) const + { + return *iDisplays[aIndex]; + } + + +EXPORT_C void CHuiEnv::Release() + { + if(iState == ENormal) + { + HUI_DEBUG(_L("CHuiEnv::Release() - Switching to background!")); + + ReportAction(THuiActionCommand(KHuiEnvReleasedActionId)); + + // Pause refresh. + PauseRefresh(); + + // Release the displays. + for(TInt i = 0; i < iDisplays.Count(); ++i) + { + iDisplays[i]->Release(); + } + + // Release the texture manager. + TBool allTexturesReleased = iTextureManager->Release(); + + // Release the rendering plugin only if all the textures are released. + if ( allTexturesReleased ) + { + HUI_DEBUG(_L("CHuiEnv::Release() - All textures released - releasing renderer")); + iRenderer->Release(); + } + if (iEffectsEngine) + { + iEffectsEngine->Release(); + } + + // Finally set the new state. + iState = EReleased; + } + } + + +EXPORT_C void CHuiEnv::RestoreL() + { + if(iState == EReleased) + { + HUI_DEBUG(_L("CHuiEnv::RestoreL() - Coming back to foreground!")); + + // Restore the renderer plugin. + iRenderer->RestoreL(); + + // Restore the texture manager. + iTextureManager->RestoreL(); + if (iEffectsEngine) + { + iEffectsEngine->RestoreL(); + } + + HUI_DEBUG(_L("CHuiEnv::RestoreL() - Restoring displays..")); + + // Restore the displays. + for(TInt i = 0; i < iDisplays.Count(); ++i) + { + iDisplays[i]->RestoreL(); + } + + // Set the state to normal + iState = ENormal; + + ReportAction(THuiActionCommand(KHuiEnvRestoredActionId)); + + // Continue refresh. + ContinueRefresh(); + + HUI_DEBUG(_L("CHuiEnv::RestoreL() - Environment restored!")); + } + } + +EXPORT_C void CHuiEnv::SetMaxCpuTime(TUint aPercent) + { + aPercent = aPercent; // to avoid warnings +#ifndef SYMBIAN_BUILD_GCE + iMaxCPUUtilization = (aPercent < KHuiEnvMaxCpuTime?aPercent:KHuiEnvMaxCpuTime); // Min does not work +#endif + } + +// Forward the respective RnD feature flag to respective components, here to TextureManager +EXPORT_C void CHuiEnv::EnableDebugFlag( TUint aRndFlag ) + { + iTextureManager->EnableTexMemoryCalculation( aRndFlag&KRndTexMemCalcFlag ); + } + +CHuiScheduler& CHuiEnv::Scheduler() + { + return *iScheduler; + } + + +TInt CHuiEnv::ReportAction(const THuiActionCommand& aCommand) + { + TInt resultError = KErrNone; + + for(TInt i = 0; i < iActionObservers.Count(); ++i) + { + TRAPD(err, iActionObservers[i].HandleActionL(aCommand)); + if(err != KErrNone && resultError == KErrNone) + { + // The first error code is returned. + resultError = err; + } + } + return resultError; + } + + +RPointerArray CHuiEnv::Displays() const + { + return iDisplays; + } + + +EXPORT_C TInt& CHuiEnv::GlesRefCounter() + { + return iGlesRefCounter; + } + +EXPORT_C CHuiEnv* CHuiEnv::Static() + { + return &(CHuiStatic::Env()); + } + +EXPORT_C CHuiThemeManager& CHuiEnv::ThemeManager() const + { + return *iThemeManager; + } + +EXPORT_C void CHuiEnv::SetFPSCounterThreshold(TUint aMilliseconds) + { + if (aMilliseconds > 0) + { + iFpsCounterThreshold = aMilliseconds; + } + else + { + iFpsCounterThreshold = 0; + } + + iFrames = 0; + iMillisecondFromFPSUpdate = 0; + } + +void CHuiEnv::SetTimeFromLastUpdate(TUint aTimeFromLastUpdate) + { + iRefreshIntervalReal = aTimeFromLastUpdate; + } + + +CHuiDisplay* CHuiEnv::CurrentDisplay() const + { + return iCurrentDisplay; + } + +EXPORT_C void CHuiEnv::ChangeRefreshLoopPriority(CActive::TPriority aPriority) + { + iRefreshLoopPriority = aPriority; + if (iPeriodic) + { + TBool wasActive = (iPeriodic->IsActive() || iRefreshLoopActive); + StopRefresh(); + delete iPeriodic; + iPeriodic = 0; + iRefreshLoopActive = EFalse; + if (wasActive) + { + StartRefresh(iRefreshIntervalTarget); + } + } + } + +TBool CHuiEnv::CPUTimeSupported() + { + TTimeIntervalMicroSeconds time; + TInt err = RThread().GetCpuTime(time); + + if (err == KErrNone && time.Int64() > 0) + { + return ETrue; + } + else + { + return EFalse; + } + } + +TBool CHuiEnv::OpenHandleToIdleCPUValueThread() + { + // find the kernel process and then the null thread + TFindProcess fp(_L("ekern.exe*")); + + TFullName kernelName; + if (fp.Next(kernelName) == KErrNone) + { + // process found, append null thread identifier + kernelName.Append(_L("::Null")); + + // find the thread + TFindThread ft(kernelName); + + TFullName threadName; + if (ft.Next(threadName) == KErrNone) + { + // open instance to the thread + if (iIdleCPUValueThread.Open(threadName) != KErrNone) + { + return EFalse; + } + } + } + else + { + // process not found + return EFalse; + } + + // success! + return ETrue; + } + +void CHuiEnv::CloseHandleToIdleCPUValueThread() + { + iIdleCPUValueThread.Close(); + } + +CHuiCanvasTextureCache& CHuiEnv::CanvasTextureCache() const + { + return *iCanvasTextureCache; + } + +EXPORT_C CHuiFxEngine* CHuiEnv::EffectsEngine() const + { + return iEffectsEngine; + } + +EXPORT_C void CHuiEnv::AddLowMemoryObserver(MHuiLowMemoryObserver * aObserver) + { + iLowMemoryObservers.Append(aObserver); + } + +EXPORT_C void CHuiEnv::RemoveLowMemoryObserver(MHuiLowMemoryObserver * aObserver) + { + TInt index = iLowMemoryObservers.Find(aObserver); + if(index != KErrNotFound) + { + iLowMemoryObservers.Remove(index); + } + } + +EXPORT_C void CHuiEnv::NotifyLowMemory(TBool /*aEnable*/) + { + //deprecated + } + + +EXPORT_C void CHuiEnv::AddMemoryLevelObserver(MHuiMemoryLevelObserver * aObserver) + { + iMemoryLevelObservers.Append(aObserver); + } + +EXPORT_C void CHuiEnv::RemoveMemoryLevelObserver(MHuiMemoryLevelObserver * aObserver) + { + TInt index = iMemoryLevelObservers.Find(aObserver); + if(index != KErrNotFound) + { + iMemoryLevelObservers.Remove(index); + } + } + +EXPORT_C void CHuiEnv::NotifyMemoryLevel(THuiMemoryLevel aMemoryLevel) + { + iMemoryLevel = aMemoryLevel; + + // notify all observers + for(TInt i=0; iSetMemoryLevel(aMemoryLevel); + } + } + +EXPORT_C THuiMemoryLevel CHuiEnv::MemoryLevel() + { + return iMemoryLevel; + }