uiacceltk/hitchcock/coretoolkit/src/HuiEnv.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
child 13 8f67d927ea57
--- /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 <eikenv.h>
+#include <bautils.h>
+#include <coemain.h>
+#include <w32std.h>
+#include <gdi.h>
+#include <e32math.h>
+
+#include "uiacceltk/HuiEnv.h"  // Class definition
+#include <ecom/implementationinformation.h>
+#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<CHuiRenderPlugin*>(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<CHuiRenderPlugin*>(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<CHuiS60Skin*>(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<CHuiEnv*>( 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<TBool> 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<CHuiDisplay*>(&aDisplay);
+    }
+
+
+void CHuiEnv::SwapBuffers(const RArray<TBool>& 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<CHuiDisplay> 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; i<iMemoryLevelObservers.Count(); i++)
+        {
+        iMemoryLevelObservers[i]->SetMemoryLevel(aMemoryLevel);
+        }
+    }
+
+EXPORT_C THuiMemoryLevel CHuiEnv::MemoryLevel()
+    {
+    return iMemoryLevel;
+    }