uiacceltk/hitchcock/coretoolkit/src/HuiFxEngine.cpp
changeset 19 f5bac0badc7e
parent 13 8f67d927ea57
child 21 6ce30188c5bf
--- a/uiacceltk/hitchcock/coretoolkit/src/HuiFxEngine.cpp	Fri Apr 16 15:56:24 2010 +0300
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiFxEngine.cpp	Mon May 03 13:22:43 2010 +0300
@@ -16,7 +16,6 @@
 */
 
 
-
 #include "HuiFxEngine.h"
 #include "HuiFxEffectParser.h"
 #include "HuiFxEffect.h"
@@ -66,6 +65,7 @@
 #endif
 #endif
     CHuiStatic::Env().AddMemoryLevelObserver(this);
+    iActiveEffectGroups.Reserve(2);
     }
 
 EXPORT_C TBool CHuiFxEngine::FxmlUsesInput1(const TDesC &aFileName)
@@ -77,6 +77,15 @@
     return EFalse;
 #endif
     }
+EXPORT_C TBool CHuiFxEngine::FxmlUsesOpaqueHint(const TDesC &aFileName)
+    {
+#ifdef HUIFX_EFFECTCACHE_ENABLED
+    return iCache->FxmlUsesOpaqueHint(aFileName);
+#endif
+#ifndef HUIFX_EFFECTCACHE_ENABLED
+    return EFalse;
+#endif    
+    }
 
 TBool CHuiFxEngine::FxmlUsesInput1(CHuiFxEffect& aEffect)
     {
@@ -282,8 +291,11 @@
     for ( TInt i = iActiveEffects.Count() - 1; i >= 0; i-- )
         {
         CHuiFxEffect* effect = iActiveEffects[i];
-        if (!effect->Changed())
+        if (!(effect->EffectFlags() & KHuiFadeEffectFlag) && !effect->Changed())
             {
+#ifdef HUIFX_TRACE
+            RDebug::Printf("void CHuiFxEngine::NotifyEffectEndObservers() calling NotifyEffectEndObserver");
+#endif
             effect->NotifyEffectEndObserver();
             }
         }    
@@ -295,13 +307,14 @@
     TInt i;
     TBool refreshRequired = EFalse;
 #ifdef HUIFX_TRACE    
-    RDebug::Print(_L("CHuiFxEngine::AdvanceTime - 0x%x "), this);   
+    RDebug::Print(_L("CHuiFxEngine::AdvanceTime - 0x%x, effect count: %d"), this, iActiveEffects.Count());   
 #endif
     // Go through the list in reverse order.
 // If the effect has ended, and has the callback set,
 // the effect will be removed, and will no longer be part of iActiveEffects set.
 // We must check if the effect is still in our list, but the indices change
 // if something is removed from the middle of the list
+    TInt skipGroup = KErrNotFound;
     for ( i = iActiveEffects.Count() - 1; i >= 0; i-- )
         {
         CHuiFxEffect* effect = iActiveEffects[i];
@@ -309,10 +322,26 @@
             {
             refreshRequired = ETrue;
             }
-        if ( i < iActiveEffects.Count() && effect == iActiveEffects[i] && !(effect->EffectFlags() & KHuiFxWaitGroupSyncronization))
+        TInt flags = effect->EffectFlags();
+        if ( !(flags & KHuiFxWaitGroupSyncronization)
+                && !(flags & KHuiFadeEffectFlag) // fade is not animated. Note, if animated effect would be used, remove this!
+                && (skipGroup == KErrNotFound || skipGroup != effect->GroupId())
+               )
             {
             // The effect is still in its place, it did not go away yet
+            TBool waitingGroupBefore = flags & KHuiFxWaitGroupToStartSyncronized;
             effect->AdvanceTime(aElapsedTime);
+            
+            if (waitingGroupBefore)
+                {
+                flags = effect->EffectFlags();
+                if (!(flags & KHuiFxReadyAndWaitingGroupToStartSyncronized) && !(flags & KHuiFxWaitGroupToStartSyncronized))
+                    {
+                    // effects in this group are all ready to start drawing. Skip this group in AdvanceTime, 
+					// that they can start syncronized on the next round
+                    skipGroup = effect->GroupId();
+                    }
+                }
             }
         }
     
@@ -332,6 +361,10 @@
 #endif // #ifdef HUIFX_TRACE    
 
     iActiveEffects.AppendL(aEffect);
+    if (iEffectObserver)
+        {
+        iEffectObserver->EffectAdded(aEffect);    
+        }
     }
 
 EXPORT_C void CHuiFxEngine::RemoveEffect(CHuiFxEffect* aEffect)
@@ -343,6 +376,10 @@
     if (i >= 0)
         {
         iActiveEffects.Remove(i);
+        if (iEffectObserver)
+            {
+            iEffectObserver->EffectComplete(aEffect);
+            }
         }
     }
 
@@ -489,7 +526,7 @@
     ASSERT((aBuffer) && (iBuffersInUse > 0));
 
 #ifdef HUIFX_RBCACHE_ENABLED
-    if(iLowGraphicsMemoryMode || IsCacheFull())
+    if(iLowGraphicsMemoryMode < EHuiMemoryLevelReduced || IsCacheFull())
         {
 #ifdef HUIFX_TRACE            
         RDebug::Print(_L("CHuiFxEngine::ReleaseRenderbuffer() --- Renderbuffer cache full! Suspectible for memory fragmentation! Cache size is %d entries."), CACHE_SIZE);
@@ -572,7 +609,7 @@
 EXPORT_C void  CHuiFxEngine::SetMemoryLevel(THuiMemoryLevel aLevel)
     {
     iLowGraphicsMemoryMode = aLevel;
-    if(iLowGraphicsMemoryMode) // != Normal
+    if(iLowGraphicsMemoryMode < EHuiMemoryLevelReduced)
         {
         ClearCache();
         }
@@ -585,19 +622,37 @@
 
 TInt CHuiFxEngine::LowMemoryState()
     {
-    return iLowGraphicsMemoryMode;
+    return iLowGraphicsMemoryMode < EHuiMemoryLevelReduced;
     }
 
 TBool CHuiFxEngine::HasActiveEffects() const
     {
 	// Don't report active effects if in SW-rendering mode
-    if(iLowGraphicsMemoryMode) // != Normal
+    if(iLowGraphicsMemoryMode < EHuiMemoryLevelReduced) 
         {
         return EFalse;
         }
     return iActiveEffects.Count() > 0;
     }
 
+TBool CHuiFxEngine::HasActiveFadeEffect() const
+    {
+    // Don't report active effects if in SW-rendering mode
+    if(iLowGraphicsMemoryMode < EHuiMemoryLevelReduced) 
+        {
+        return EFalse;
+        }
+    TInt effectCount = iActiveEffects.Count();
+    for (TInt count  = 0; count < effectCount; count++)
+        {
+        if (iActiveEffects[count]->EffectFlags() & KHuiFadeEffectFlag)
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
 void CHuiFxEngine::ClearCache()
     {
     // Release cached render targets from effects
@@ -626,48 +681,142 @@
     
     ASSERT(iBuffersInCache == 0);    
     }
-	
+
+TInt CHuiFxEngine::FindEffectGroup(TInt aGroup)
+    {
+    for (TInt i=0 ; i < iActiveEffectGroups.Count();i++)
+        {
+        if (iActiveEffectGroups[i].iGroup == aGroup)
+            {
+            return i; 
+            }
+        }
+    return KErrNotFound;
+    }
+
 EXPORT_C void CHuiFxEngine::BeginGroupEffect(TInt aGroup)
 	{
-	TInt index = iActiveEffectGroups.Find(aGroup);
+#ifdef HUIFX_TRACE   
+	RDebug::Printf("CHuiFxEngine::BeginGroupEffect(TInt aGroup %d) >>", aGroup);
+#endif
+	// Multiple grouped effects at the same time are not supported. 
+    // Same visual might participate different groups, which will mess up the effect
+    if (iActiveEffectGroups.Count()>0)
+        {
+        // delete previous groups
+        while(iActiveEffectGroups.Count())
+            {
+            TInt groupId = iActiveEffectGroups[0].iGroup;
+            for ( TInt i = iActiveEffects.Count() - 1; i >= 0; i-- )
+                {
+                if (iActiveEffects[i]->GroupId() == groupId)
+                    {
+                    iActiveEffects[i]->ClearEffectFlag(KHuiFxReadyAndWaitingGroupToStartSyncronized);
+                    iActiveEffects[i]->ClearEffectFlag(KHuiFxWaitGroupToStartSyncronized);
+                    iActiveEffects[i]->ClearEffectFlag(KHuiFxWaitGroupSyncronization);
+                    }
+                
+                }
+            iActiveEffectGroups.Remove(0);
+            }
+        }
+	
+	TInt index = FindEffectGroup(aGroup);
+	
 	if (index == KErrNotFound)
 		{
-		iActiveEffectGroups.Append(aGroup);
-		}
-	else
-		{
-		// group already exists
+        const TEffectGroupStruct item(aGroup);
+		iActiveEffectGroups.Append(item);
 		}
 	}
 
+// This will add effect to this group. Do not call this function more than once for single effect 
 EXPORT_C TInt CHuiFxEngine::ActiveGroupEffect()
 	{
-	if (iActiveEffectGroups.Count() > 0)
-		{
-		return iActiveEffectGroups[iActiveEffectGroups.Count()-1];
-		}
-	else
-		{
-		return KErrNotFound;
-		}
+	TInt index = iActiveEffectGroups.Count();
+	if (index == 0)
+	    {
+        return KErrNotFound;
+	    }
+	while(--index >= 0)
+        {
+		// group is alive until all its effects have been drawn once. .iEndCalled is to prevent
+		// another effect entering into this group
+        const TEffectGroupStruct& item = iActiveEffectGroups[index];
+        if (!item.iEndCalled) 
+            { 
+			return iActiveEffectGroups[index].iGroup;
+            }
+        }
+    return KErrNotFound;
 	}
 
+EXPORT_C TBool CHuiFxEngine::AddEffectToGroup(TInt aGroup)
+    {
+    TInt index = FindEffectGroup(aGroup);
+    if (index != KErrNotFound)
+        {
+        // keep count of effects in this group. All must draw atleast once, before
+        // syncronized group effect may start
+        iActiveEffectGroups[index].iWaiting++;
+#ifdef HUIFX_TRACE
+        RDebug::Printf("CHuiFxEngine::AddEffectToGroup - %d, waiting in group: %d", aGroup, iActiveEffectGroups[index].iWaiting);
+#endif
+        return ETrue;
+        }
+    return EFalse;
+    }
+
 EXPORT_C void CHuiFxEngine::StartGroupEffect(TInt aGroup)
 	{
-	TInt index = iActiveEffectGroups.Find(aGroup);
+#ifdef HUIFX_TRACE
+    RDebug::Printf("CHuiFxEngine::StartGroupEffect(TInt aGroup %d) >>", aGroup);
+#endif	    
+	TInt index = FindEffectGroup(aGroup);
 	if (index != KErrNotFound)
 		{
-		iActiveEffectGroups.Remove(index);
-	
+		iActiveEffectGroups[index].iEndCalled = ETrue; // this group will not take any more participants
 		for ( TInt i = iActiveEffects.Count() - 1; i >= 0; i-- )
 			{
 			CHuiFxEffect* effect = iActiveEffects[i];
 			TInt flags = effect->EffectFlags();
 			if ((flags & KHuiFxWaitGroupSyncronization) && (effect->GroupId() == aGroup))
 				{
-				flags &= ~KHuiFxWaitGroupSyncronization;
-				effect->SetEffectFlags(flags);
+                effect->ClearEffectFlag(KHuiFxWaitGroupSyncronization);
+                effect->SetEffectFlag(KHuiFxWaitGroupToStartSyncronized);
 				}
 			}
 		}
 	}
+
+void CHuiFxEngine::NotifyEffectReady(TInt aGroupId)
+    {
+#ifdef HUIFX_TRACE    
+    RDebug::Print(_L("CHuiFxEngine::NotifyEffectReady - %d"), aGroupId);
+#endif
+    TInt index = FindEffectGroup(aGroupId);
+    if (index != KErrNotFound)
+        {
+        iActiveEffectGroups[index].iWaiting--;    
+#ifdef HUIFX_TRACE
+        RDebug::Print(_L("CHuiFxEngine::NotifyEffectReady - waiting %d in group %d"), iActiveEffectGroups[index].iWaiting , aGroupId);
+#endif        
+        if (iActiveEffectGroups[index].iWaiting == 0)
+            {
+            // set in motion all effects in this group
+	        iActiveEffectGroups.Remove(index);
+            for ( TInt i = iActiveEffects.Count() - 1; i >= 0; i-- )
+                {
+                CHuiFxEffect* effect = iActiveEffects[i];
+                TInt flags = effect->EffectFlags();
+#ifdef HUIFX_TRACE
+                RDebug::Print(_L("CHuiFxEngine::NotifyEffectReady - effect 0x%x, group: %d, flags 0x%x"), effect, effect->GroupId(), effect->EffectFlags());
+#endif                
+                if ((flags & KHuiFxReadyAndWaitingGroupToStartSyncronized) && (effect->GroupId() == aGroupId))
+                    {
+                    effect->ClearEffectFlag(KHuiFxReadyAndWaitingGroupToStartSyncronized);
+                    }
+                }
+            }
+        }
+    }