uiacceltk/hitchcock/coretoolkit/src/HuiFxEffect.cpp
changeset 0 15bf7259bb7c
child 7 433cbbb6a04b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiFxEffect.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,542 @@
+/*
+* Copyright (c) 2008 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 "HuiFxEffect.h"
+#include "HuiFxGroupLayer.h"
+#include "HuiRenderPlugin.h"
+#include "HuiCmdBufferBrush.h" // MHuiEffectable
+
+EXPORT_C CHuiFxEffect* CHuiFxEffect::NewL(CHuiFxEngine& aEngine)
+    {
+    CHuiFxEffect* e = new (ELeave) CHuiFxEffect( aEngine );
+    CleanupStack::PushL(e);
+    e->ConstructL();
+    CleanupStack::Pop(e);
+    return e;
+    }
+
+CHuiFxEffect::CHuiFxEffect( CHuiFxEngine& aEngine ) :
+    iEngine( &aEngine )
+    {
+#ifdef HUIFX_TRACE    
+    RDebug::Print(_L("CHuiFxEffect::CHuiFxEffect - 0x%x"), this);
+#endif
+    }
+EXPORT_C CHuiFxEffect *CHuiFxEffect::CloneL() const
+{
+   CHuiFxEffect *effect = new (ELeave)CHuiFxEffect(*iEngine);
+   effect->iRoot = iRoot->CloneL();
+   effect->iEffectEndObserver = iEffectEndObserver;
+   effect->iHandle = iHandle;
+   return effect;
+}
+EXPORT_C void CHuiFxEffect::SetExtRect( TRect *aExtRect )
+    {
+    iRoot->SetExtRect(aExtRect);
+    }
+EXPORT_C void CHuiFxEffect::SetVisual( CHuiVisual *aVisual )
+    {
+    iRoot->SetVisual(aVisual);
+    }
+EXPORT_C void CHuiFxEffect::SetVisual( MHuiEffectable *aEffectable )
+    {
+    iRoot->SetVisual(aEffectable);
+    }
+EXPORT_C void CHuiFxEffect::SetEngine( CHuiFxEngine *aEngine )
+    {
+    iEngine = aEngine;
+    iEngine->AddEffectL(this);
+    }
+
+EXPORT_C void CHuiFxEffect::ConstructL( )
+    {
+    iRoot = CHuiFxGroupLayer::NewL(ETrue);
+#ifndef HUIFX_EFFECTCACHE_ENABLED    
+    iEngine->AddEffectL(this);
+#endif
+    }
+
+EXPORT_C CHuiFxEffect::~CHuiFxEffect()
+    {
+    delete iRoot;
+    iRoot = NULL;
+    
+    NotifyEffectEndObserver();
+    
+    ReleaseCachedRenderTarget();
+    
+    iEngine->RemoveEffect(this);
+#ifdef HUIFX_TRACE    
+    RDebug::Print(_L("CHuiFxEffect::~CHuiFxEffect - 0x%x"), this);
+#endif
+    }
+
+void CHuiFxEffect::NotifyEffectEndObserver()
+    {
+    if ( iEffectEndObserver )
+        {
+        // The callback can be called only once when the effect finishes
+        iEffectEndObserver->AlfGfxEffectEndCallBack( iHandle );
+        iEffectEndObserver = NULL;
+        iHandle = 0;
+        }    
+    }
+
+EXPORT_C void CHuiFxEffect::AddLayerL(const CHuiFxLayer* aLayer)
+    {
+    iRoot->AddLayerL(aLayer);
+    }
+
+void CHuiFxEffect::ReleaseCachedRenderTarget()
+    {
+    if (iCachedRenderTarget)
+        {
+        iEngine->ReleaseRenderbuffer(iCachedRenderTarget);
+        iCachedRenderTarget = NULL;
+        }                
+    }
+
+void CHuiFxEffect::PrepareCachedRenderTarget(const TPoint& aPosition, const TSize& aSize, TBool aClear, TBool aEnableBackground)
+    {
+    // If size has chnaged, we must delete old one
+    if (iCachedRenderTarget && 
+        iCachedRenderTarget->Size() != aSize)
+        {
+        ReleaseCachedRenderTarget();
+        }            
+    
+    // Accure new buffer
+    if (!iCachedRenderTarget)
+        {
+        iCachedRenderTarget = iEngine->AcquireRenderbuffer(aSize, EFalse);                    
+        }    
+    
+    if (iCachedRenderTarget)
+        {
+        // Set render buffer position in screen coordinates
+        iCachedRenderTarget->SetPosition(aPosition);                 
+        
+        // Enable background if needed
+       iCachedRenderTarget->EnableBackground(aEnableBackground);
+
+       // Clear if requested
+        if (aClear)
+            {
+            iCachedRenderTarget->PrepareForReuse(iCachedRenderTarget->Size());
+            }        
+        }    
+    }
+
+void CHuiFxEffect::ForceCachedRenderTargetUsage(TBool aUseCachedRenderTarget)
+    {
+    iForcedUseCachedRenderTarget = aUseCachedRenderTarget;
+    }
+
+TBool CHuiFxEffect::IsCachedRenderTargetPreferred() const
+    {
+    // Prefer use cached render target if 
+    //
+    // 1. I am filter effect. 
+    //    Note that this does not provide good performance if effect 
+    //    is animated, but noncached version does not work visually correctly 
+    //    in rotated display if effect is applied to background as well.
+    //    -> TODO: Return EFalse if effect has animated filter which does not use background pixels 
+    // 
+    // 2. User has set force flag
+    //
+    if (iForcedUseCachedRenderTarget || iRoot->IsFiltered())
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+TBool CHuiFxEffect::IsCachedRenderTargetSupported() const
+    {
+    // Can use cached render target if
+    //
+    // 1. Render supports it (openvg for now).
+    // 2. Engine is not in low memory mode.
+    //
+    if (iEngine->EngineType() == EHuiFxEngineVg10 && 
+        !iEngine->LowMemoryState()) // normal
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+TBool CHuiFxEffect::CachedDraw(CHuiGc& aGc, const TRect& aDisplayRect, TBool aRefreshCachedRenderTarget, TBool aOpaque)
+    {
+    RRegion dummy;
+    TBool ret = CachedDraw(aGc, aDisplayRect, aRefreshCachedRenderTarget, aOpaque, dummy);
+    dummy.Close();
+    return ret;
+    }
+
+// TODO: effect area should be reduced if aClipRegion is smaller than aDisplayRect.
+TBool CHuiFxEffect::CachedDraw(CHuiGc& aGc, const TRect& aDisplayRect, TBool aRefreshCachedRenderTarget, TBool aOpaque, const TRegion& aClipRegion, TInt aAlpha)
+    {
+#ifdef HUIFX_TRACE    
+    RDebug::Print(_L("CHuiFxEffect::CachedDraw - 0x%x"), this);
+#endif    
+    iFramesDrawn++;
+    if (!CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowVisualPBufferSurfaces))
+        {
+        return EFalse;
+        }
+            
+    
+    CHuiFxRenderbuffer* target = NULL;
+    
+    // Prepare all layers
+    TRect displayArea = aGc.DisplayArea();
+    TRect targetArea = aDisplayRect;
+    targetArea.Intersection(displayArea);
+
+    if (targetArea.Width() <= 0 || targetArea.Height() <= 0)
+        {
+        // Not visible
+        return ETrue;
+        }
+
+    if (!iEngine || !iRoot)
+        {
+        return EFalse;
+        }
+
+    if (iEngine->LowMemoryState())
+        {
+        // No memory, no effects.
+        return EFalse;
+        }
+    
+    // Check if margins are allowed to be used for this effect
+    if (EffectFlags() & KHuiFxEffectDisableMarginsFlag)
+        {
+        iRoot->EnableMargin(EFalse);
+        }
+    
+    iRoot->SetTargetRect(targetArea);
+    iRoot->SetSourceRect(targetArea);        
+    iRoot->SetDisplayArea(displayArea);
+    
+    TRAPD(err, iRoot->PrepareDrawL(*iEngine));
+    
+    if (err != KErrNone)
+        {
+        return EFalse;
+        }
+
+    if (IsCachedRenderTargetSupported() && IsCachedRenderTargetPreferred())
+        {
+        // Background needs to be captured from surface if effect uses background AND 
+        // Visual is transparent or margin is enabled AND
+        // Background has not been disabled with a effect specific flag
+        TBool enableBackground = IsAppliedToBackground() && (!aOpaque || iRoot->IsMarginEnabled()) && !(EffectFlags() & KHuiFxDisableBackground);
+        
+        // Check if cache is up-to date or does it need to be refreshed
+        TBool cachedRenderTargetNeedsRefresh = (iRoot->Changed() || aRefreshCachedRenderTarget || enableBackground);
+
+        // Try to apply also margins, we cannot just use aDisplayRect directly
+        TRect targetRect = iRoot->VisualRect();
+        
+        // Size is always same as target rect. It contains margins if those are enabled.
+        TSize cachedRenderTargetSize = targetRect.Size();        
+                
+        // Prepare cached offscreen render target
+        PrepareCachedRenderTarget(targetRect.iTl, cachedRenderTargetSize, cachedRenderTargetNeedsRefresh, enableBackground);
+        
+        // If it is available, then lets do it 
+        if (iCachedRenderTarget)
+            {
+            // Disable clipping, otherwise strange things happen.
+            aGc.Disable(CHuiGc::EFeatureClipping);             
+            if (cachedRenderTargetNeedsRefresh)
+                {
+                // Render to cached render target
+                iRoot->Draw(*iEngine, aGc, *iCachedRenderTarget, *iCachedRenderTarget);                
+#ifdef HUIFX_TRACE    
+                RDebug::Print(_L("CHuiFxEffect::CachedDraw - refreshed cached render buffer 0x%x"), this);
+#endif
+                }            
+
+            if (aClipRegion.Count())
+                {
+                aGc.Enable(CHuiGc::EFeatureClipping);
+                aGc.PushClip();
+                aGc.Clip(aClipRegion);
+                }
+            
+            // Write cached buffer to the display
+            iEngine->Composite(aGc, *iCachedRenderTarget, targetRect.iTl, aOpaque && !(EffectFlags() & KHuiFxAlwaysBlend), aAlpha);
+
+            if (aClipRegion.Count())
+                {
+                aGc.PopClip();
+                }
+            
+            aGc.Enable(CHuiGc::EFeatureClipping);
+#ifdef HUIFX_TRACE    
+            RDebug::Print(_L("CHuiFxEffect::CachedDraw - Cached render buffer drawn 0x%x"), this);
+            RDebug::Print(_L("CHuiFxEffect::CachedDraw - displayrect: %i,%i, %i,%i "), 
+                    aDisplayRect.iTl.iX,
+                    aDisplayRect.iTl.iY,
+                    aDisplayRect.iBr.iX,
+                    aDisplayRect.iBr.iY);
+#endif            
+            }
+        else
+            {
+            // It might not be available e.g. in low memory situations, just indiacte that we could not draw.
+            return EFalse;
+            }
+        }
+    else
+        {
+        // Release cached render target just in case it is reserved for some reason
+        ReleaseCachedRenderTarget();
+
+        // Use default onscreen render target
+        if (!target)
+            {
+            target = iEngine->DefaultRenderbuffer();
+            }
+        
+        if (!target)
+            {
+            return EFalse;
+            }
+        
+        // Normal drawing
+        iRoot->Draw(*iEngine, aGc, *target, *target);
+        }
+                
+    return ETrue;    
+    }
+
+EXPORT_C TBool CHuiFxEffect::Draw(CHuiGc& aGc, const TRect& aDisplayRect)
+    {
+    // Prepare all layers
+#ifdef HUIFX_TRACE    
+    RDebug::Print(_L("CHuiFxEffect::Draw - 0x%x"), this);
+#endif
+    iFramesDrawn++;
+    if (!CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowVisualPBufferSurfaces))
+        {
+        return EFalse;
+        }
+            
+    TRect displayArea = aGc.DisplayArea();
+    TRect targetArea = aDisplayRect;
+    targetArea.Intersection(displayArea);
+
+    if (targetArea.Width() <= 0 || targetArea.Height() <= 0)
+        {
+        // Not visible
+        return ETrue;
+        }
+
+    if (!iEngine || !iRoot)
+        {
+        return EFalse;
+        }
+
+    if (iEngine->LowMemoryState())
+        {
+        // No memory, no effects.
+        return EFalse;
+        }
+    
+    // Check if margins are allowed to be used for this effect
+    if (EffectFlags() & KHuiFxEffectDisableMarginsFlag)
+        {
+        iRoot->EnableMargin(EFalse);
+        }
+    
+    iRoot->SetDisplayArea(displayArea);
+    iRoot->SetTargetRect(targetArea);
+    iRoot->SetSourceRect(targetArea);
+    
+    TRAPD(err, iRoot->PrepareDrawL(*iEngine));
+    
+    if (err != KErrNone)
+        {
+        return EFalse;
+        }
+    
+    CHuiFxRenderbuffer* target = iEngine->DefaultRenderbuffer();
+    
+    if (!target)
+        {
+        return EFalse;
+        }
+
+    iRoot->Draw(*iEngine, aGc, *target, *target);
+    return ETrue;
+    }
+
+EXPORT_C TBool CHuiFxEffect::VisualArea(TRect& aRect) const
+    {
+    return iRoot->VisualArea(aRect);
+    }
+
+EXPORT_C CHuiFxEngine& CHuiFxEffect::Engine() const
+    {
+    return *iEngine;
+    }
+
+EXPORT_C TBool CHuiFxEffect::Changed()
+    {
+    TBool changed = iRoot->Changed();
+    return changed;
+    }
+    
+EXPORT_C void CHuiFxEffect::SetEffectEndObserver( MAlfGfxEffectObserver* aEffectEndObserver, TInt aHandle )
+    {
+    iEffectEndObserver = aEffectEndObserver;
+    iHandle = aHandle;
+    }
+
+EXPORT_C void CHuiFxEffect::SetEffectFlags( TInt aFlags )
+    {
+    iFlags = aFlags;
+    }
+
+EXPORT_C void CHuiFxEffect::SetEffectGroup(TInt aGroupId)
+    {
+    iGroupId = aGroupId;
+    }
+
+EXPORT_C TInt CHuiFxEffect::EffectFlags()
+    {
+    return iFlags;
+    }
+
+EXPORT_C TInt CHuiFxEffect::GroupId()
+    {
+    return iGroupId;
+    }
+
+EXPORT_C void CHuiFxEffect::AdvanceTime(TReal32 aElapsedTime)
+    {
+    if (iFlags & KHuiFxDelayRunUntilFirstFrameHasBeenDrawn)
+        {
+        if (iFramesDrawn)
+            {
+            if (iFramesDrawn == 1)
+                {
+                aElapsedTime = 0;
+                iFramesDrawn++;
+                }
+            iRoot->AdvanceTime(aElapsedTime);
+            }
+        else
+            {
+            }
+        }
+    else
+        {
+        iRoot->AdvanceTime(aElapsedTime);
+        }
+    }
+    
+EXPORT_C TBool CHuiFxEffect::IsAnimated() const
+    {
+    if (iRoot && iRoot->IsAnimated())
+        {
+        return ETrue;        
+        }
+    else
+        {
+        return EFalse;
+        }    
+    }
+
+EXPORT_C TBool CHuiFxEffect::IsTransformed() const
+    {
+    if (iRoot && iRoot->IsTransformed())
+        {
+        return ETrue;        
+        }
+    else
+        {
+        return EFalse;
+        }            
+    }
+
+TBool CHuiFxEffect::IsFiltered() const
+    {
+    if (iRoot && iRoot->IsFiltered())
+        {
+        return ETrue;        
+        }
+    else
+        {
+        return EFalse;
+        }            
+    }
+
+TBool CHuiFxEffect::IsAppliedToBackground()
+    {
+    if (iRoot && iRoot->LayerCount())
+        {
+        if (iRoot->Layer(0).Type() == ELayerTypeGroup)
+            {
+            // If first layer after root is group, then effect is not applied to background (?)
+            return EFalse;    
+            }
+        else
+            {
+            if (IsFiltered())
+                {
+                return ETrue;
+                }
+            else
+                {
+                // Not filter effect -> cannot be applied to background.
+                return EFalse;
+                }
+            } 
+        }            
+    return EFalse;    
+    }
+
+TBool CHuiFxEffect::IsSemitransparent() const
+    {
+    if (iRoot && iRoot->IsSemitransparent())
+        {
+        return ETrue;        
+        }
+    else
+        {
+        return EFalse;
+        }            
+    }
+
+void CHuiFxEffect::FxmlVisualInputs(RArray<THuiFxVisualSrcType> &aArray)
+    {
+    iRoot->FxmlVisualInputs(aArray);
+    }