uiacceltk/hitchcock/coretoolkit/src/HuiEnv_stubs.cpp
changeset 0 15bf7259bb7c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiEnv_stubs.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,557 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#include <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"
+
+
+/* Constants */
+const TInt KHuiEnvDefaultNormalRefreshIntervalMs = 40;
+
+/* 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;
+
+// @todo: this should be obsolete once scheduling can adapt to CPU load
+const TInt KHuiEnvDefaultBusyRefreshIntervalMs = 2 * KHuiEnvDefaultNormalRefreshIntervalMs;
+
+/** Threshold number for refreshes that don't have any effect. When exceeded,
+    refresh is paused. */
+const TInt KIdleRefreshCountThreshold = 3;
+
+
+// to get around nasty ownership problem with texture manager interface
+void NullTextureManagerPtr(TAny* aPtrToPtr)
+    {
+    if (aPtrToPtr)
+        {
+        CHuiTextureManager** ptr = (CHuiTextureManager**)aPtrToPtr;
+        *ptr = 0;
+        }
+    }
+
+
+void CHuiEnv::SetTextureManager(CHuiTextureManager& aManager)
+    {
+    iTextureManager = &aManager;
+    }
+
+
+
+void CHuiEnv::StopRefresh()
+    {
+    HUI_DEBUG(_L("CHuiEnv::StopRefresh()"));
+    if(iPeriodic)
+        {
+        iPeriodic->Cancel();
+        }
+    }
+
+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
+    }
+
+
+void CHuiEnv::AdvanceTime(TReal32 aElapsedTime)
+    {
+    HUI_DEBUGF( _L("CHuiEnv::AdvanceTime() - Started") )
+
+    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)
+        {
+        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(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);                
+        }
+
+    // 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;
+                }
+            }
+        }
+    
+    TBool continueRefresh = ETrue;
+
+    if(somethingUpdated)
+        {
+        HUI_DEBUGF( _L("CHuiEnv::AdvanceTime() - Swap buffers") )
+
+        SwapBuffers(displayRefreshed);
+        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
+        }
+
+	displayRefreshed.Close(); // Not needed any more
+
+    // 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();
+
+    if (continueRefresh)
+        {
+        // Refresh rate adjustment
+        if (usedMaxCPUUtilization)
+            {
+            TUint millisecondsUsedInRefresh = CHuiStatic::MilliSecondsSinceUpdateTime();
+
+            TUint totalLoopTime = (millisecondsUsedInRefresh * 100) / usedMaxCPUUtilization;
+    
+            if (totalLoopTime >= iRefreshIntervalTarget)
+                {
+                iRefreshInterval = (millisecondsUsedInRefresh*(100-usedMaxCPUUtilization))/usedMaxCPUUtilization;
+                StartRefresh(iRefreshInterval);        
+                }
+            else if (iRefreshIntervalTarget != iRefreshInterval)
+                {
+                iRefreshInterval = iRefreshIntervalTarget; 
+                StartRefresh(iRefreshInterval);
+                }
+            else
+                {
+                // otherwise just let the periodic run as it already has good interval set
+                }
+            }
+
+        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") );
+    }
+
+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);
+    }
+
+
+
+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))
+        	{
+     		iDisplays[i]->RenderSurface().SwapBuffers();
+        	}
+        }
+    }
+
+
+void CHuiEnv::CreateResourceReaderLC(TResourceReader& aReader, TInt aResourceId) const
+    {
+    CCoeEnv* coe = CCoeEnv::Static();
+    if (!coe)
+    		{
+    		User::Leave(KErrNotSupported);
+    	  }
+    coe->CreateResourceReaderLC(aReader, aResourceId);
+    }
+
+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
+        }
+    }
+
+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;
+    }
+
+
+
+void CHuiEnv::SetTimeFromLastUpdate(TUint aTimeFromLastUpdate)
+    {
+    iRefreshIntervalReal = aTimeFromLastUpdate;
+    }
+
+
+CHuiDisplay* CHuiEnv::CurrentDisplay() const
+    {
+    return iCurrentDisplay;    
+    }
+
+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;    
+    }