--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiDisplay.cpp Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,1685 @@
+/*
+* Copyright (c) 2006-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: Implementation of CHuiDisplay, a drawing buffer into which a
+* the toolkit contents (visuals) are drawn.
+*
+*/
+
+
+
+#include "uiacceltk/HuiDisplay.h" // Class definition
+#include "uiacceltk/HuiStatic.h"
+#include "HuiRenderPlugin.h"
+#include "HuiRenderSurface.h"
+#include "uiacceltk/HuiEnv.h"
+#include "HuiRosterImpl.h"
+#include "uiacceltk/HuiSkin.h"
+#include "uiacceltk/HuiTransformation.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiTexture.h"
+#include "uiacceltk/HuiProbe.h"
+#include "uiacceltk/HuiS60Skin.h"
+#include "uiacceltk/HuiGc.h"
+#ifndef __SERIES60_30__
+#include "HuiTargetBitmap.h"
+#endif
+#include "uiacceltk/HuiControlGroup.h"
+#include "alf/alfconstants.h"
+
+#ifdef RD_ALF_IN_PLATFORM
+#include <displaylayoutmetrics.cdl.h>
+#endif // RD_ALF_IN_PLATFORM
+
+#include <AknsRendererWrapper.h>
+#include <AknsDrawUtils.h>
+
+#include <coecntrl.h>
+#include <uiacceltk/huidisplaybackgrounditem.h>
+#include "huiskinbackroundlayout.h"
+#include "HuiFxEngine.h"
+
+const TUid KHuiInternalFbsBitmapBufferGcUid = {0x2000e5a3};
+
+//#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+
+
+// *** Class CHuiFbsBitmapBufferGc
+
+class CHuiFbsBitmapBufferGc: public CBase, public MHuiFbsBitmapBufferGc
+ {
+ public:
+ CHuiFbsBitmapBufferGc(CFbsBitmap* aBitmap) :iBitmap(aBitmap) {};
+
+ private: // From MHuiFbsBitmapBufferGc
+ void ReleaseGc();
+ CFbsBitmap* Bitmap();
+
+ private:
+ CFbsBitmap* iBitmap; // not owned
+ };
+
+
+void CHuiFbsBitmapBufferGc::ReleaseGc()
+ {
+ // Line "delete(this)" should always be the last line in this method.
+ // If you change this method behaviour make sure you know what caveats "delete(this)" has.
+ delete(this);
+ }
+
+CFbsBitmap* CHuiFbsBitmapBufferGc::Bitmap()
+ {
+ return iBitmap;
+ }
+
+// *** Class CHuiDisplay
+
+CHuiDisplay::CHuiDisplay(CHuiEnv& aEnv, RWindow* aNativeWindow, TInt aDisplayType, TUid aBackBufferUid )
+ : iEnv(aEnv),
+ iDisplayType(aDisplayType),
+ iActive(ETrue),
+ iBackgroundColor(KRgbBlack),
+ iUpdateRenderState(ETrue),
+ iUsageHint(EHuiDisplayUsageGeneric),
+ iOnForeground(ETrue),
+ iScreenBufferUid(aBackBufferUid),
+ iUseTransformedDirtyRegions(EFalse),
+ iDrawVisualOutline( EDrawVisualOutlineNone ),
+ iNativeWindow(aNativeWindow)
+ {
+ }
+
+CHuiDisplay::CHuiDisplay(CHuiEnv& aEnv, CCoeControl* aNativeControl, TInt aDisplayType, TUid aBackBufferUid )
+ : iEnv(aEnv),
+ iDisplayType(aDisplayType),
+ iNativeControl(aNativeControl),
+ iSize(0, 0),
+ iActive(ETrue),
+ iBackgroundColor(KRgbBlack),
+ iUpdateRenderState(ETrue),
+ iUsageHint(EHuiDisplayUsageGeneric),
+ iOnForeground(ETrue),
+ iScreenBufferUid(aBackBufferUid),
+ iUseTransformedDirtyRegions(EFalse),
+ iDrawDirtyRegions( EFalse ),
+ iDrawVisualOutline( EDrawVisualOutlineNone )
+ {
+ }
+
+
+void CHuiDisplay::ConstructL(const TRect& aRect, CHuiRoster* aSharedRoster)
+ {
+ HUI_DEBUG1(_L("CHuiDisplay::ConstructL - Free memory in beginning: %i"), HuiUtil::FreeMemory());
+
+ // Register this display to receive foreground lost / gained events.
+/* CCoeEnv* coeEnv = CCoeEnv::Static();
+ if(coeEnv && NativeWindow())
+ {
+ coeEnv->AddMessageMonitorObserverL(*this);
+ NativeWindow()->EnableVisibilityChangeEvents();
+ }
+*/
+
+ iSize = aRect.Size();
+
+ // Create a rendering surface.
+ iRenderSurface = CHuiStatic::Renderer().CreateRenderSurfaceL(*this);
+
+ iCurrentDirtyRegions = &iDirtyRegions;
+
+ // Preserve previous dirty rect info only if the surface uses both dirty rects and double
+ // buffering
+ TUint flags = MHuiRenderSurface::EFlagUseDirtyRects | MHuiRenderSurface::EFlagUseDoubleBuffering;
+ TBool preservePreviousDirtyRectInfo = ((iRenderSurface->Flags() & flags) == flags);
+
+ if (preservePreviousDirtyRectInfo)
+ {
+ iPreviousDirtyRegions = &iDirtyRegions2;
+ }
+
+ // Create a control roster.
+ if(aSharedRoster)
+ {
+ iRoster.Set(aSharedRoster, EHuiDoesNotHaveOwnership);
+ }
+ else
+ {
+ // Construct a private roster.
+ CHuiRosterImpl* roster = new (ELeave) CHuiRosterImpl(this);
+ iRoster.Set(roster, EHuiHasOwnership);
+ }
+
+ // Transformation for the entire display.
+ iTransform = CHuiTransformation::NewL();
+ // Window transformation for the entire display.
+ iWindowTransform = CHuiTransformation::NewL();
+
+ SetScreenBufferLock(EFalse);
+
+ // Create a graphics context.
+ iGc = CHuiStatic::Renderer().CreateGcL();
+
+ HUI_DEBUG1(_L("CHuiDisplay::ConstructL - Free memory after GC created: %i"), HuiUtil::FreeMemory());
+
+ SetVisibleArea(TRect(TPoint(0, 0), iSize));
+
+ HUI_DEBUG1(_L("CHuiDisplay::ConstructL - Free memory after surface created: %i"), HuiUtil::FreeMemory());
+
+ if ( !CHuiStatic::Renderer().Allows( EHuiRenderPluginAllowPBufferSurfaces ) )
+ // There is no default render surface, so make this one current
+ // immediately to enable texture loading.
+ {
+ iRenderSurface->MakeCurrent();
+ }
+
+ // When dirty regions are transformed it is possible to avoid
+ // full display refresh in many cases -> better performance.
+ iGc->EnableTransformedClippingRects(iUseTransformedDirtyRegions);
+
+ HUI_DEBUG1(_L("CHuiDisplay::ConstructL - Free memory when exiting ConstructL: %i"), HuiUtil::FreeMemory());
+ }
+
+
+EXPORT_C CHuiDisplay::~CHuiDisplay()
+ {
+ HUI_DEBUG1(_L("CHuiDisplay %x destructor"), this);
+
+ // Unregister this display from foreground gained / lost events.
+// CCoeEnv* coeEnv = CCoeEnv::Static();
+// if(coeEnv && NativeWindow())
+// {
+// coeEnv->RemoveMessageMonitorObserver(*this);
+// }
+
+ // Notify observers of deletion.
+
+ if(iScreenBufferObserver)
+ {
+ iScreenBufferObserver->HandleScreenBufferEvent(iScreenBufferUid, MHuiScreenBufferObserver::EDeleted);
+ }
+
+ for(TInt i = 0; i < iDeletionObservers.Count(); ++i)
+ {
+ iDeletionObservers[i].NotifyDisplayDeletion(*this);
+ }
+ iDeletionObservers.Reset();
+ iRefreshObservers.Reset();
+ iVisibleAreaObservers.Reset();
+ iRosterObservers.Reset();
+
+ iDirtyRegions.Close();
+ iDirtyRegions2.Close();
+ if ( iCurrentDirtyRegions )
+ {
+ iCurrentDirtyRegions->Close();
+ }
+ iCurrentDirtyRegions = NULL;
+
+ if ( iPreviousDirtyRegions )
+ {
+ iPreviousDirtyRegions->Close();
+ }
+ iPreviousDirtyRegions = NULL;
+
+ delete iRenderSurface;
+ iRenderSurface = NULL;
+
+ delete iGc;
+ iGc = NULL;
+
+ delete iTransform;
+ iTransform = NULL;
+
+ delete iWindowTransform;
+ iWindowTransform = NULL;
+
+ iEnv.RemoveDisplay(*this);
+
+ iNativeControl = NULL;
+
+ iBackgroundItems.Close();
+
+ delete iForegroundTexture;
+
+ delete iForegroundBitmapGc;
+ delete iForegroundBitmapDevice;
+ iForegroundBitmap = NULL;
+ }
+
+TReal32 CHuiDisplay::UnitValue() const
+ {
+#ifdef RD_ALF_IN_PLATFORM
+ // this will be correct according to the currently loaded layout pack for the current display
+ if (CCoeEnv::Static())
+ {
+ return Display_Layout_Metrics::UnitValue();
+ }
+ else
+ {
+ return 1.0f;
+ }
+#else // RD_ALF_IN_PLATFORM
+ // not supported
+ return 1.0f;
+#endif // RD_ALF_IN_PLATFORM
+ }
+
+void CHuiDisplay::MonitorWsMessage(const TWsEvent& aEvent)
+ {
+ switch(aEvent.Type())
+ {
+ case EEventWindowVisibilityChanged:
+ {
+ const TBool wasOnForeground = iOnForeground;
+
+// iOnForeground = !(aEvent.VisibilityChanged()->iFlags&TWsVisibilityChangedEvent::ENotVisible);
+
+ if ( !wasOnForeground && iOnForeground )
+ {
+ // Becomes visible, force refresh.
+ // This is needed for example in case of resolution changes.
+ SetDirty();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+
+CHuiGc* CHuiDisplay::Gc()
+ {
+ ASSERT(iGc != NULL);
+
+ return iGc;
+ }
+
+EXPORT_C CCoeControl* CHuiDisplay::NativeControl()
+ {
+ return iNativeControl;
+ }
+
+
+EXPORT_C RDrawableWindow* CHuiDisplay::NativeWindow()
+ {
+ if (iNativeWindow)
+ {
+ return iNativeWindow;
+ }
+
+ else if(iNativeControl)
+ {
+ return iNativeControl->DrawableWindow();
+ }
+
+ return 0;
+ }
+
+
+EXPORT_C CHuiEnv& CHuiDisplay::Env()
+ {
+ return iEnv;
+ }
+
+
+EXPORT_C MHuiRenderSurface& CHuiDisplay::RenderSurface() const
+ {
+ return *iRenderSurface;
+ }
+
+
+EXPORT_C CHuiRoster& CHuiDisplay::Roster()
+ {
+ return iRoster.Ref();
+ }
+
+
+EXPORT_C const CHuiRoster& CHuiDisplay::Roster() const
+ {
+ return iRoster.Ref();
+ }
+
+
+EXPORT_C void CHuiDisplay::Show(TBool aShow)
+ {
+ iRenderSurface->HandleVisibilityEvent(aShow);
+
+ // Update projection and GC state on the next refresh.
+ iUpdateRenderState = ETrue;
+ }
+
+
+CHuiRosterImpl& CHuiDisplay::RosterImpl() const
+ {
+ return STATIC_CAST(CHuiRosterImpl&, iRoster.NonConstRef());
+ }
+
+
+EXPORT_C void CHuiDisplay::SetSizeL(const TSize& aSize)
+ {
+ iSize = aSize;
+
+ // Update projection and GC state on the next refresh.
+ iUpdateRenderState = ETrue;
+
+ if(iRenderSurface)
+ {
+ iRenderSurface->SetSizeL(iSize);
+ }
+ }
+
+
+EXPORT_C TSize CHuiDisplay::Size() const
+ {
+ return iSize;
+ }
+
+
+EXPORT_C TRect CHuiDisplay::VisibleArea() const
+ {
+ return iGc->DisplayArea();
+ }
+
+
+EXPORT_C void CHuiDisplay::SetVisibleArea(const TRect& aArea)
+ {
+ if(iGc)
+ {
+ // If clipping has been defined for visible are, it is now invalid so disable.
+ SetVisibleAreaClippingRect(TRect(0,0,0,0));
+
+ iGc->SetDisplayArea(aArea);
+ // Make sure everything gets redrawn.
+ SetDirty();
+
+ // Can change the roster rect only if the roster is own
+ // \todo This should be prevented also for other shared roster types.
+ RosterImpl().SetRect(aArea);
+
+ // Update projection and GC state on the next refresh.
+ iUpdateRenderState = ETrue;
+
+ // Inform observers.
+ for(TInt i = 0; i < iVisibleAreaObservers.Count(); ++i)
+ {
+ iVisibleAreaObservers[i].NotifyDisplayVisibleAreaChanged(*this);
+ }
+ }
+ }
+
+
+EXPORT_C void CHuiDisplay::Activate(TBool aActivate)
+ {
+ iActive = aActivate;
+
+ if(iActive)
+ {
+ // This is the display now using the roster. Only meaningful when the
+ // roster is shared between many displays.
+ RosterImpl().SetDisplay(this);
+ }
+ }
+
+
+EXPORT_C TBool CHuiDisplay::Active() const
+ {
+ return iActive;
+ }
+
+
+EXPORT_C void CHuiDisplay::SetOrientation(CHuiGc::TOrientation aOrientation)
+ {
+ if (iGc->Orientation() == aOrientation)
+ {
+ return;
+ }
+
+ iGc->SetOrientation(aOrientation);
+
+ // The effective visible area, as seen by the UI, changes.
+ RosterImpl().SetRect(VisibleArea());
+ for(TInt i = 0; i < iVisibleAreaObservers.Count(); ++i)
+ {
+ iVisibleAreaObservers[i].NotifyDisplayVisibleAreaChanged(*this);
+ }
+
+ SetDirty();
+
+ // Update projection and GC state on the next refresh.
+ iUpdateRenderState = ETrue;
+
+ // Clear effect engine cache as it most likely now contains buffers which
+ // sizes are not very well reusable. It would be better to have "fifo" or
+ // something in the cache implementation but until that just release everything here
+ // when display layout changes.
+ CHuiFxEngine* fxEngine = Env().EffectsEngine();
+ if (fxEngine)
+ {
+ fxEngine->ClearCache();
+ }
+ }
+
+
+EXPORT_C CHuiGc::TOrientation CHuiDisplay::Orientation() const
+ {
+ return iGc->Orientation();
+ }
+
+
+EXPORT_C void CHuiDisplay::SetDirty()
+ {
+ // Mark the entire display dirty.
+ HUI_DEBUG(_L("CHuiDisplay::SetDirty() - called."));
+
+ if ( iWholeDisplayAreaIsDirty )
+ {
+ return;
+ }
+
+ TRect displayArea = iGc->DisplayArea();
+ AddDirtyRegion(displayArea, *iCurrentDirtyRegions);
+ if (iPreviousDirtyRegions)
+ {
+ AddDirtyRegion(displayArea, *iPreviousDirtyRegions);
+ }
+ iEnv.ContinueRefresh();
+
+ iWholeDisplayAreaIsDirty = ETrue;
+ }
+
+
+TBool CHuiDisplay::IsDirty() const
+ {
+ //iRoster->ScanDirty();
+ //return iDirtyRegions.Count() > 0;
+
+ /** @todo Determine this better. There should be a way to quickly
+ determine if the display needs to be updated; although
+ a visual change scan is also a possiblity if it is done
+ once per frame. */
+
+ return iActive;
+ }
+
+
+void CHuiDisplay::AddDirtyRegion(const TRect& aDirtyRegion)
+ {
+ // Whole screen has been set dirty, no need to add new areas.
+ if (iWholeDisplayAreaIsDirty && iGotDirtyReports)
+ {
+ return;
+ }
+
+ TRect clippedDirtyRect = aDirtyRegion;
+
+ if (UseTransformedDirtyRegions())
+ {
+ TransformDirtyRect(clippedDirtyRect);
+ }
+
+ ClipDirtyRect(clippedDirtyRect);
+
+ // If whole screen is set dirty, update flag which can be used to avoid
+ // further unnecessary dirty area calculations
+ if (iGc && (iGc->DisplayArea() == clippedDirtyRect))
+ {
+ iWholeDisplayAreaIsDirty = ETrue;
+ }
+
+ // At least one dirty region was reported.
+ iGotDirtyReports = ETrue;
+
+ AddDirtyRegion(clippedDirtyRect, *iCurrentDirtyRegions);
+ }
+
+
+void CHuiDisplay::CombineAndAddDirtyRegion(const TRect& aPrevDirtyRegion, TRect& aDirtyRegion)
+ {
+ // aPrevDirtyRegion has already been transformed, but aDirtyRegion is not (yet)
+ // transformed.
+
+ TRect dirtyRect = aDirtyRegion;
+
+ if (!dirtyRect.IsEmpty() && UseTransformedDirtyRegions())
+ {
+ TransformDirtyRect(dirtyRect);
+ }
+
+ TRect transformedNewDirtyRect = dirtyRect;
+
+ // If the whole display is not dirty, update current combined dirty region
+ if (!iWholeDisplayAreaIsDirty)
+ {
+ dirtyRect.BoundingRect(aPrevDirtyRegion);
+
+ ClipDirtyRect(dirtyRect);
+
+ if (iGc && (iGc->DisplayArea() == dirtyRect))
+ {
+ // If whole screen is set dirty, update flag which can be used to avoid
+ // further unnecessary dirty area calculations
+ iWholeDisplayAreaIsDirty = ETrue;
+ }
+
+ // At least one dirty region was reported.
+ iGotDirtyReports = ETrue;
+ AddDirtyRegion(dirtyRect, *iCurrentDirtyRegions);
+ }
+ // We must only transform the (new) dirtyregion, not combine or anything else here
+ aDirtyRegion = transformedNewDirtyRect;
+ }
+
+
+void CHuiDisplay::AddDirtyRegion(const TRect& aDirtyRegion, RDirtyRegions& aRegions, TBool /*aGrow*/)
+ {
+ TBool combined = ETrue;
+ TInt i = 0;
+ TInt k = 0;
+
+ aRegions.Append(aDirtyRegion);
+
+ // Combine overlapping regions.
+ while(combined && aRegions.Count() > 1)
+ {
+ combined = EFalse;
+
+ // Check that none of the regions overlap each other.
+ /** @todo Performance? */
+ for(i = 0; i < aRegions.Count(); ++i)
+ {
+ TRect expanded = aRegions[i];
+ expanded.Grow(20, 20); //(8, 8);
+
+ for(k = i + 1; k < aRegions.Count(); ++k)
+ {
+ // E: comment out for lazy merging
+ if(aRegions[k].Intersects(expanded))
+ {
+ // Remove the latter one.
+ aRegions[i].BoundingRect(aRegions[k]);
+ aRegions.Remove(k);
+ --k;
+ combined = ETrue;
+ }
+ }
+ }
+ }
+ }
+
+
+TBool CHuiDisplay::Refresh()
+ {
+ HUI_DEBUGF(_L("CHuiDisplay::Refresh() - Entering."));
+ HUI_PROBE_PROGRAMFLOW_ENTER(MHuiProbe::EProgramFlowPointRefresh)
+
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+ RDebug::Print(_L("CHuiDisplay::Refresh: starting measuring."));
+ TTime startTime;
+ startTime.UniversalTime();
+#endif
+
+
+ // Prevent display refresh, if the display is on background.
+ if(!iOnForeground || IsScreenBufferLocked())
+ {
+ return EFalse;
+ }
+
+ TBool useDirtyRects = (RenderSurface().Flags() & MHuiRenderSurface::EFlagUseDirtyRects)
+ == MHuiRenderSurface::EFlagUseDirtyRects;
+
+ iWholeDisplayAreaIsDirty = EFalse;
+
+ if(iUpdateRenderState)
+ {
+ // Set state when requested.
+ iGc->InitState();
+ iGc->SetProjection();
+
+ iUpdateRenderState = EFalse;
+ }
+
+ // Let the skin know that we're now drawing in this context.
+ iEnv.Skin().SetContext(*iGc);
+
+ TRect displayArea = iGc->DisplayArea();
+
+ // Notify observers of the display refresh.
+ TInt i = 0;
+ for(i = 0; i < iRefreshObservers.Count(); ++i)
+ {
+ iRefreshObservers[i].NotifyDisplayRefreshStarted(*this);
+ }
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+ TTime afterNotifiedTime;
+ afterNotifiedTime.UniversalTime();
+#endif
+
+
+ if (IsDisplayTypeTvOut())
+ {
+ // Scale shared roster to Tv-out screen
+ TReal32 scaleFactorX = (TReal32)Size().iWidth / (TReal32)RosterImpl().Rect().Width();
+ TReal32 scaleFactorY = (TReal32)Size().iHeight / (TReal32)RosterImpl().Rect().Height();
+ // Calculate window transformations
+ iWindowTransform->LoadIdentity();
+ iWindowTransform->Scale(scaleFactorX, scaleFactorY, 1.f);
+ }
+
+// THuiRenderer renderer = iEnv.Renderer();
+ TBool hasTransformations = iTransform->Count() != 0 || iWindowTransform->Count() != 0 || RosterImpl().HasTransformedControlGroups();
+ TBool cantUseDirtyRectsInThisFrame = hasTransformations && !UseTransformedDirtyRegions();
+
+ // When refresh is forced, there is no need to scan dirty areas.
+ if (iEnv.RefreshMode() != EHuiRefreshModeForced)
+ {
+ // Flag that tells us if any dirty regions were reported for
+ // this frame.
+ iGotDirtyReports = (iCurrentDirtyRegions->Count() > 0);
+
+ // Tell all visuals to post their dirty regions (for the current state).
+ if (UseTransformedDirtyRegions())
+ {
+ RosterImpl().ScanTransformedDirty(*iGc, this);
+ }
+ else
+ {
+ RosterImpl().ScanDirty();
+ }
+
+ if (!useDirtyRects || cantUseDirtyRectsInThisFrame || iEnv.EffectsEngine()->HasActiveEffects())
+ {
+ // Just redraw everything
+ iCurrentDirtyRegions->Reset();
+ AddDirtyRegion(displayArea, *iCurrentDirtyRegions, EFalse);
+ }
+ }
+ else
+ {
+ iGotDirtyReports = ETrue;
+
+ // Just redraw everything since determining dirty regions is
+ // complicated with a transformed display.
+ iCurrentDirtyRegions->Reset();
+ AddDirtyRegion(displayArea);
+ }
+
+ // We can return now if there are no new or old dirty areas
+ if (!iGotDirtyReports && (!iPreviousDirtyRegions || (iPreviousDirtyRegions->Count() == 0)))
+ {
+ iCurrentDirtyRegions->Reset();
+ return EFalse;
+ }
+
+ // Form the real list of dirty regions by combining the dirty regions of
+ // this frame and the previous frame (this is needed when buffer swapping
+ // is used; with buffer copying a single list of dirty regions would
+ // suffice).
+ RDirtyRegions dirty;
+ for(i = 0; i < iCurrentDirtyRegions->Count(); ++i)
+ {
+ dirty.Append((*iCurrentDirtyRegions)[i]);
+ }
+ if (iPreviousDirtyRegions)
+ {
+ for(i = 0; i < iPreviousDirtyRegions->Count(); ++i)
+ {
+ AddDirtyRegion((*iPreviousDirtyRegions)[i], dirty, EFalse);
+ }
+ }
+
+ // Do initializations for new frame
+ // initnewframe may clear the screen, and it may be that
+ // the clipping rectangle is not set up correctly
+ // atleast if the dirty area tracking is on..
+ iGc->SetPenColor(iBackgroundColor);
+ iGc->InitNewFrame();
+
+ if ( iDrawDirtyRegions )
+ {
+ // Show dirty.
+ // This will draw the whole background with black.
+ iGc->SetPenColor(KRgbBlack);
+ iGc->Disable(CHuiGc::EFeatureClipping);
+ iGc->Clear();
+ }
+
+
+ // Set up clipping.
+ TInt markedClipStackCount = iGc->ClipStackCount();
+ if(useDirtyRects)
+ {
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ }
+
+ // Assume that we succeed to clean the dirty regions
+ TBool dirtyRegionsCleaned = ETrue;
+
+ // Set dirty rect in render surface to minimize screen update
+ // Only implemented for BitGdi renderer for now
+ TRect mergedDirtyRect;
+ if (dirty.Count() > 0)
+ {
+ mergedDirtyRect = dirty[0];
+ }
+
+ if (useDirtyRects)
+ {
+ // When Bitgdi renderer used set dirty rect in render surface
+ // to minimize screen update in CHuiBitgdiRenderSurface::SwapBuffers
+ if (dirty.Count() == 1)
+ {
+ ClipDirtyRect(mergedDirtyRect, VisibleAreaClippingRect());
+ iRenderSurface->SetDirtyRect(mergedDirtyRect);
+ }
+ else if (dirty.Count() > 1)
+ {
+ for(i = 1; i < dirty.Count(); ++i)
+ {
+ TRect r(dirty[i]);
+ // check top left corner to expand or not
+ if (r.iTl.iX < mergedDirtyRect.iTl.iX)
+ {
+ mergedDirtyRect.iTl.iX = r.iTl.iX;
+ }
+ if (r.iTl.iY < mergedDirtyRect.iTl.iY)
+ {
+ mergedDirtyRect.iTl.iY = r.iTl.iY;
+ }
+ // check bottom right corner to expand or not
+ if (mergedDirtyRect.iBr.iX < r.iBr.iX)
+ {
+ mergedDirtyRect.iBr.iX = r.iBr.iX;
+ }
+ if (mergedDirtyRect.iBr.iY < r.iBr.iY)
+ {
+ mergedDirtyRect.iBr.iY = r.iBr.iY;
+ }
+ }
+
+ ClipDirtyRect(mergedDirtyRect, VisibleAreaClippingRect());
+ iRenderSurface->SetDirtyRect(mergedDirtyRect);
+ }
+ else
+ {
+ // for PC lint
+ }
+
+ if ( iDrawDirtyRegions )
+ {
+ // This will disable the clipping of the frame buffer when
+ // blitting on the screen.
+ iRenderSurface->SetDirtyRect(displayArea);
+ }
+ }
+
+ // Merge into max one dirty area when HW accelrated drawing is used
+ if (useDirtyRects && IsRendererHWAccelerated())
+ {
+ dirty.Reset();
+ dirty.Append(mergedDirtyRect);
+ }
+
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+ RDebug::Print(_L("CHuiDisplay::Refresh: Merged dirty rect: %d %d %d %d"),
+ mergedDirtyRect.iTl.iX,
+ mergedDirtyRect.iTl.iY,
+ mergedDirtyRect.iBr.iX,
+ mergedDirtyRect.iBr.iY);
+#endif
+
+ // Usually there is only one dirty region (if any).
+ for(i = 0; i < dirty.Count(); ++i)
+ {
+ // Set up the clipping rectangle.
+ TRect dirtyRect = dirty[i];
+ ClipDirtyRect(dirtyRect, VisibleAreaClippingRect());
+
+ iGc->PushClip();
+ iGc->Clip(dirtyRect);
+
+ if ( iForegroundBitmapGc )
+ {
+ // If we are in SW rendering mode, then SW bitmap is blended.
+ // However, it's possible that nothing is drawn below, so clear
+ // background.
+ const TRgb oldBgColor = iBackgroundColor;
+ iBackgroundColor = KRgbBlack;
+ iBackgroundColor.SetAlpha(0);
+ ClearWithColor( dirtyRect );
+ iBackgroundColor = oldBgColor;
+ }
+
+ // Clear background for the dirty area
+ if (iBackgroundItems.Count() != 0)
+ {
+ ClearWithBackgroundItems(dirtyRect);
+ }
+ else
+ {
+ switch (iClearBackground)
+ {
+ case EClearWithColor:
+ {
+ ClearWithColor(dirtyRect);
+ break;
+ }
+ case EClearWithSkinBackground:
+ {
+ ClearWithSkinBackground(dirtyRect);
+ break;
+ }
+ case EClearNone:
+ default:
+ {
+ // Don't do anything
+ break;
+ }
+ }
+ }
+
+ if ( iForegroundBitmapGc )
+ {
+ iForegroundBitmapGc->Reset();
+ iForegroundBitmapGc->SetClippingRegion( iGc->ClipRegion() );
+
+ TRgb clearColor = KRgbBlack;
+ clearColor.SetAlpha(0x00);
+
+ iForegroundBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
+ iForegroundBitmapGc->SetPenColor(clearColor);
+ iForegroundBitmapGc->SetBrushColor(clearColor);
+ iForegroundBitmapGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ iForegroundBitmapGc->Clear();
+ iForegroundBitmapGc->Reset();
+ }
+
+ for(TInt i = 0; i < iRosterObservers.Count(); i++)
+ {
+ iRosterObservers[i].NotifyRosterDrawStart(*this);
+ }
+
+ // Prepare dirty visuals for drawing
+ // Draw only if the prepare was successful
+ if (RosterImpl().PrepareDraw())
+ {
+ // Draw all the dirty visuals (that are touching dirty regions).
+ iGc->Enable(CHuiGc::EFeatureBlending);
+ RosterImpl().Draw(*iGc, this);
+ }
+ else
+ {
+ HUI_DEBUGF(_L("CHuiDisplay::Refresh() - Failed to prepare drawing!"));
+ dirtyRegionsCleaned = EFalse;
+ }
+
+ for(TInt i = 0; i < iRosterObservers.Count(); i++)
+ {
+ iRosterObservers[i].NotifyRosterDrawEnd(*this);
+ }
+
+ if (iForegroundTexture)
+ {
+ DrawForegroundTexture();
+ }
+
+ // Return to the clipping rectangle that was in use previously.
+ iGc->PopClip();
+ }
+
+ dirty.Reset();
+
+ // There must be no disparity in the number of pushed clipping rectangles.
+ // (equivalent to __ASSERT_ALWAYS)
+ if(iGc->ClipStackCount() > markedClipStackCount)
+ {
+ THuiPanic::Panic(THuiPanic::EDisplayClipStackUnpopped);
+ }
+ if(iGc->ClipStackCount() < markedClipStackCount)
+ {
+ THuiPanic::Panic(THuiPanic::EDisplayClipStackEarlyPop);
+ }
+
+ // Reset and flip if we managed to clean (draw) everything
+ if (iPreviousDirtyRegions && dirtyRegionsCleaned && iCurrentDirtyRegions->Count() > 0)
+ {
+ RDirtyRegions* tmp = iPreviousDirtyRegions;
+ iPreviousDirtyRegions = iCurrentDirtyRegions;
+ iCurrentDirtyRegions = tmp;
+ }
+
+ // Clear current dirty regions
+ iCurrentDirtyRegions->Reset();
+
+ // Trick to swap gles buffers if we are drawing idle screens before refresh loop is going to
+ // sleep.
+ if( IsRendererHWAccelerated() && !iGotDirtyReports && !iScreenBufferObserver)
+ {
+ //RenderSurface().SwapBuffers(); [ohi]
+ }
+
+ // Tell the screen buffer observer that the buffer is complete
+ if(iScreenBufferObserver)
+ {
+ SetScreenBufferLock(ETrue); // the observer should do unlock!
+
+ TRect rect(VisibleArea()); // This is not the real display rect in ALF display case(!)
+ TRect dirtyRect(mergedDirtyRect);
+
+ // Update screen buffer GC bitmap
+ if (DisplayType() != CHuiDisplay::EDisplayOffScreenBuffer)
+ {
+ TRAP_IGNORE(CHuiStatic::Renderer().UpdateOffScreenBitmapL(*this));
+ }
+
+ if (iScreenBufferObserver->ScreenBufferComplete(iScreenBufferUid, rect, dirtyRect))
+ {
+ SetScreenBufferLock(EFalse);
+ }
+ }
+
+ iWholeDisplayAreaIsDirty = EFalse;
+
+ HUI_PROBE_PROGRAMFLOW_EXIT(MHuiProbe::EProgramFlowPointRefresh)
+ HUI_DEBUGF(_L("CHuiDisplay::Refresh() - Exiting."));
+
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+ TTime endTime;
+ endTime.UniversalTime();
+ TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000;
+ TInt notifyTimeInMs = afterNotifiedTime.MicroSecondsFrom( startTime ).Int64()/1000;
+ TInt restTimeInMs = endTime.MicroSecondsFrom( afterNotifiedTime ).Int64()/1000;
+
+ RDebug::Print(_L("CHuiDisplay::Refresh: took %i ms"), timeInMs);
+ RDebug::Print(_L("CHuiDisplay::Refresh: notify refresh observers took %i ms"), notifyTimeInMs);
+ RDebug::Print(_L("CHuiDisplay::Refresh: rest took %i ms"), restTimeInMs);
+
+#endif
+
+
+ // If something was reported (even if eventually clipped), we'll say that
+ // there was some activity. If it was clipped and did not show up on the
+ // display, it may soon (re)appear, so let's be cautious.
+ return iGotDirtyReports;
+ }
+
+
+EXPORT_C CHuiTransformation& CHuiDisplay::Transformation() const
+ {
+ return *iTransform;
+ }
+
+
+EXPORT_C void CHuiDisplay::SetClearBackgroundL(TClearMode aClearBackground)
+ {
+ // Make sure that background resource allocation is succeeded.
+ if(aClearBackground == EClearWithSkinBackground)
+ {
+ iEnv.Skin().TextureL(EHuiSkinBackgroundTexture);
+ }
+
+ iClearBackground = aClearBackground;
+ iBackgroundItems.Reset();
+ }
+
+
+EXPORT_C void CHuiDisplay::SetBackgroundColor(const TRgb& aBackgroundColor)
+ {
+ iBackgroundColor = aBackgroundColor;
+ }
+
+
+EXPORT_C void CHuiDisplay::SetUseDepth(TBool aUseDepth)
+ {
+ iUseDepth = aUseDepth;
+ }
+
+
+EXPORT_C TUint8* CHuiDisplay::CaptureLC(TSize& aSize) const
+ {
+ return iGc->CaptureLC(aSize);
+ }
+
+
+EXPORT_C void CHuiDisplay::SetQuality(THuiQuality aRenderingQuality)
+ {
+ if(iGc)
+ {
+ iGc->SetQuality(aRenderingQuality);
+ SetDirty();
+ }
+ }
+
+
+EXPORT_C THuiQuality CHuiDisplay::Quality() const
+ {
+ if(iGc)
+ {
+ return iGc->Quality();
+ }
+ return EHuiQualityAccurate;
+ }
+
+
+EXPORT_C void CHuiDisplay::Release()
+ {
+ // Free the render surface.
+ ASSERT(iRenderSurface != NULL);
+ HUI_DEBUG(_L("CHuiDisplay::Release() - Releasing render surface."));
+ iRenderSurface->Release();
+
+ HUI_DEBUG(_L("CHuiDisplay::Release() - Display released."));
+ }
+
+
+EXPORT_C void CHuiDisplay::RestoreL()
+ {
+ HUI_DEBUG(_L("CHuiDisplay::RestoreL() - Restoring display resources."));
+
+ // Reconfigure graphics context when display is refreshed.
+ iUpdateRenderState = ETrue;
+
+ // Create a rendering surface.
+ iRenderSurface->RestoreL();
+ }
+
+
+EXPORT_C TInt CHuiDisplay::DisplayType()
+ {
+ return iDisplayType;
+ }
+
+EXPORT_C TUid CHuiDisplay::ScreenBufferUid()
+ {
+ return iScreenBufferUid;
+ }
+
+
+EXPORT_C TBool CHuiDisplay::IsScreenBufferLocked() const
+ {
+ return iIsScreenBufferLocked;
+ }
+
+
+EXPORT_C void CHuiDisplay::SetScreenBufferLock(TBool aLock)
+ {
+ iIsScreenBufferLocked = aLock;
+ }
+
+
+EXPORT_C MHuiBufferDrawer* CHuiDisplay::GetDrawingInterface(const TUid& /*aInterfaceUid*/)
+ {
+ return (MHuiBufferDrawer*)NULL;
+ }
+
+
+EXPORT_C MHuiGc* CHuiDisplay::GetGraphicsContext(const TUid& aInterfaceUid)
+ {
+ MHuiGc* gc = NULL;
+ if (aInterfaceUid == KHuiInternalFbsBitmapBufferGcUid)
+ {
+ if (iEnv.Renderer() == EHuiRendererBitgdi)
+ {
+ CFbsBitmap* backBuffer = iRenderSurface->BackBuffer()->FbsBitmap();
+ CHuiFbsBitmapBufferGc* bitmapGc = new CHuiFbsBitmapBufferGc(backBuffer);
+ gc = (MHuiFbsBitmapBufferGc*) bitmapGc;
+ }
+ else
+ {
+ if ( DisplayType() != CHuiDisplay::EDisplayOffScreenBuffer )
+ {
+ gc =(MHuiFbsBitmapBufferGc*) new CHuiFbsBitmapBufferGc(
+ CHuiStatic::Renderer().OffScreenBitmap());
+ }
+ }
+ }
+ return gc;
+ }
+
+EXPORT_C void CHuiDisplay::AddScreenBufferObserverL(MHuiScreenBufferObserver* aObserver)
+ {
+ if (DisplayType() != CHuiDisplay::EDisplayOffScreenBuffer)
+ {
+ CHuiStatic::Renderer().EnableOffScreenBitmapL(0);
+ }
+
+ iScreenBufferObserver = aObserver;
+ SetScreenBufferLock(EFalse);
+ }
+
+
+EXPORT_C void CHuiDisplay::RemoveScreenBufferObserver()
+ {
+ iScreenBufferObserver = NULL;
+
+ if (DisplayType() != CHuiDisplay::EDisplayOffScreenBuffer)
+ {
+ CHuiStatic::Renderer().DisableOffScreenBitmap();
+ }
+
+ SetScreenBufferLock(EFalse);
+ }
+
+
+EXPORT_C MHuiScreenBufferObserver* CHuiDisplay::ScreenBufferObserver()
+ {
+ return iScreenBufferObserver;
+ }
+
+
+EXPORT_C void CHuiDisplay::DrawScreenBuffer()
+ {
+ if (DisplayType() != CHuiDisplay::EDisplayOffScreenBuffer)
+ {
+ TRAP_IGNORE(CHuiStatic::Renderer().DrawOffScreenBitmapToWindowL(*this));
+ }
+ }
+
+
+void CHuiDisplay::ClearChanged()
+ {
+ RosterImpl().ClearChanged();
+ }
+
+EXPORT_C void CHuiDisplay::SetUsageL(TUint aUsageHint)
+ {
+ iUsageHint = aUsageHint;
+ if (iRenderSurface)
+ {
+ iRenderSurface->HandleDisplayUsageChangeL();
+ }
+ }
+
+EXPORT_C TUint CHuiDisplay::Usage() const
+ {
+ return iUsageHint;
+ }
+
+
+EXPORT_C TInt CHuiDisplay::GetPreferredTextureFormats(RPointerArray<CHuiDisplay::CTextureBitmapFormat>& aTextureFormats)
+ {
+ // Note: It would be better if preferred display mode was asked from the renderer itself
+ TInt err = KErrNone;
+ CHuiDisplay::CTextureBitmapFormat* format = NULL;
+ if (!IsRendererHWAccelerated())
+ {
+ format = new CHuiDisplay::CTextureBitmapFormat(EColor64K, EGray256);
+ if (format != NULL)
+ {
+ err = aTextureFormats.Append(format);
+ }
+ }
+ else
+ {
+ format = new CHuiDisplay::CTextureBitmapFormat(EColor16MA, ENone);
+ if (format != NULL)
+ {
+ err = aTextureFormats.Append(format);
+ if (!err)
+ {
+ format = new CHuiDisplay::CTextureBitmapFormat(EColor64K, EGray256);
+ if (format != NULL)
+ {
+ err = aTextureFormats.Append(format);
+ }
+ }
+ }
+ }
+
+ if (err)
+ {
+ delete(format);
+ }
+
+ return (format == NULL) ? KErrNoMemory : err;
+ }
+
+
+CHuiTransformation& CHuiDisplay::WindowTransformation() const
+ {
+ return *iWindowTransform;
+ }
+
+EXPORT_C TBool CHuiDisplay::IsDisplayTypeTvOut() const
+ {
+ return((iDisplayType == CHuiDisplay::EDisplayTvOut) ||
+ (iDisplayType == CHuiDisplay::EDisplayTvOutWide) ||
+ ((iDisplayType == CHuiDisplay::EDisplayNormal) &&
+ ((iScreenBufferUid == KHuiUidBackBufferTvOutNormal) ||
+ (iScreenBufferUid == KHuiUidBackBufferTvOutWide))));
+ }
+
+TBool CHuiDisplay::IsRendererBitgdi() const
+ {
+ return (iEnv.Renderer() == EHuiRendererBitgdi);
+ }
+
+TBool CHuiDisplay::IsRendererHWAccelerated() const
+ {
+ return (iEnv.Renderer() != EHuiRendererBitgdi);
+ }
+
+void CHuiDisplay::ClipDirtyRect(TRect& aRect)
+ {
+ // Check if dirty regions partially outside display are reported, limit
+ // inside display area.
+ if(iGc)
+ {
+ TRect displayRect = iGc->DisplayArea();
+ // If partially outside display area, we use intersection instead.
+ if (aRect.Intersects(displayRect))
+ {
+ aRect.Intersection(displayRect);
+ }
+ }
+ }
+
+void CHuiDisplay::TransformDirtyRect(TRect& aRect)
+ {
+ if ( iGc )
+ {
+ THuiRealRect realDirtyRect(aRect);
+ iGc->TransformDirtyRect(realDirtyRect);
+ aRect = TRect(HUI_ROUND_FLOAT_TO_INT(realDirtyRect.iTl.iX), HUI_ROUND_FLOAT_TO_INT(realDirtyRect.iTl.iY),
+ HUI_ROUND_FLOAT_TO_INT(realDirtyRect.iBr.iX), HUI_ROUND_FLOAT_TO_INT(realDirtyRect.iBr.iY));
+ }
+ }
+
+TBool CHuiDisplay::UseTransformedDirtyRegions() const
+ {
+ return iUseTransformedDirtyRegions;
+ }
+
+EXPORT_C void CHuiDisplay::ShowDirtyRegions( TBool aShow )
+ {
+ iDrawDirtyRegions = aShow;
+ }
+
+EXPORT_C void CHuiDisplay::SetDrawVisualOutline( TUint aDrawVisualOutline )
+ {
+ iDrawVisualOutline = aDrawVisualOutline;
+ }
+
+TUint CHuiDisplay::DrawVisualOutline() const
+ {
+ return iDrawVisualOutline;
+ }
+
+TBool CHuiDisplay::IsDirtyScanNeeded() const
+ {
+ TUint flag = MHuiRenderSurface::EFlagUseDirtyRects;
+ TBool useDirtyRects = (RenderSurface().Flags() & flag) == flag;
+ return (useDirtyRects || !iGotDirtyReports);
+ }
+
+EXPORT_C void CHuiDisplay::SetBackgroundItemsL(const RArray<THuiDisplayBackgroundItem>& aItems)
+ {
+ iClearBackground = EClearNone;
+ iBackgroundItems.Reset();
+ for(TInt i = 0; i < aItems.Count(); ++i)
+ {
+ iBackgroundItems.AppendL(aItems[i]);
+ }
+ if (IsRendererHWAccelerated())
+ {
+ CHuiS60Skin* s60skin = static_cast<CHuiS60Skin*>(&iEnv.Skin());
+ s60skin->UpdateBackgroundsL(iBackgroundItems);
+ }
+ SetDirty();
+ }
+
+void CHuiDisplay::ClearWithColor(TRect aRect)
+ {
+ if (!IsRendererHWAccelerated())
+ {
+ BitgdiClearWithColor(aRect);
+ }
+ else
+ {
+ HWAcceleratedClearWithColor(aRect);
+ }
+ }
+
+void CHuiDisplay::ClearWithSkinBackground(TRect aRect)
+ {
+ if (!IsRendererHWAccelerated())
+ {
+ BitgdiClearWithSkinBackground(aRect);
+ }
+ else
+ {
+ HWAcceleratedClearWithSkinBackground(aRect);
+ }
+ }
+
+void CHuiDisplay::ClearWithBackgroundItems(TRect aRect)
+ {
+ if (!IsRendererHWAccelerated())
+ {
+ BitgdiClearWithBackgroundItems(aRect);
+ }
+ else
+ {
+ HWAcceleratedClearWithBackgroundItems(aRect);
+ }
+ }
+
+
+void CHuiDisplay::BitgdiClearWithColor(TRect /*aRect*/)
+ {
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ iGc->Clear();
+ }
+
+void CHuiDisplay::BitgdiClearWithSkinBackground(TRect aRect)
+ {
+ CCoeControl* nativeControl = NativeControl();
+ CHuiS60Skin* s60skin = static_cast<CHuiS60Skin*>(&iEnv.Skin());
+ CAknsBasicBackgroundControlContext* bgcontext = (CAknsBasicBackgroundControlContext*)s60skin->SkinControlContext();
+
+ CFbsBitGc* bitGc = iRenderSurface->BackBuffer()->Gc();
+ if (nativeControl)
+ {
+ bgcontext->SetRect(TRect(TPoint(0, -nativeControl->Position().iY), HuiUtil::ScreenSize()));
+ }
+ else
+ {
+ bgcontext->SetRect(TRect(TPoint(0, 0), HuiUtil::ScreenSize()));
+ }
+
+ // Draw the background onto the framebuffer
+ MAknsSkinInstance* skin = CHuiStatic::SkinInstance();
+ TPoint tl = aRect.iTl;
+ TRect rect = aRect;
+ bgcontext->SetBitmap(KAknsIIDQsnBgScreen);
+
+ AknsDrawUtils::DrawBackground(skin, bgcontext, NULL,
+ *bitGc, tl, rect,
+ KAknsDrawParamDefault);
+ }
+
+void CHuiDisplay::BitgdiClearWithBackgroundItems(TRect aRect)
+ {
+ CHuiS60Skin* s60skin = static_cast<CHuiS60Skin*>(&iEnv.Skin());
+ CAknsBasicBackgroundControlContext* bgcontext = (CAknsBasicBackgroundControlContext*)s60skin->SkinControlContext();
+
+ CFbsBitGc* bitGc = iRenderSurface->BackBuffer()->Gc();
+ THuiDisplayBackgroundItem item;
+ MAknsSkinInstance* skin = CHuiStatic::SkinInstance();
+
+ for (TInt index = 0; index < iBackgroundItems.Count(); index++)
+ {
+ TRect clearRect = aRect;
+ TRect skinRect = TRect(0,0,0,0);
+ TRect dummy = TRect(0,0,0,0);
+
+ item = iBackgroundItems[index];
+ switch (item.ClearMode())
+ {
+ case EClearWithSkinBackground:
+ if (skin)
+ {
+ GetRectForItem(item.SkinBackground(), dummy, skinRect);
+ bgcontext->SetRect(skinRect);
+ bgcontext->SetBitmap(item.SkinBackground());
+ skinRect.Intersection(aRect);
+ skinRect.Intersection(item.Rect());
+ AknsDrawUtils::DrawBackground(skin, bgcontext, NULL,
+ *bitGc, skinRect.iTl, skinRect,
+ KAknsDrawParamDefault);
+ break;
+ } // else fall through
+ case EClearWithColor:
+ clearRect.Intersection(item.Rect());
+ if (!clearRect.IsEmpty())
+ {
+ bitGc->SetBrushColor(item.Color());
+ bitGc->Clear(clearRect);
+ }
+ break;
+ case EClearNone:
+ default:
+ // do nothing...
+ break;
+ }
+ }
+
+ }
+
+void CHuiDisplay::HWAcceleratedClearWithColor(TRect /*aRect*/)
+ {
+ iGc->SetPenColor(iBackgroundColor);
+ iGc->SetPenAlpha(iBackgroundColor.Alpha());
+ iGc->Disable(CHuiGc::EFeatureBlending);
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ iGc->Clear();
+ }
+
+void CHuiDisplay::HWAcceleratedClearWithSkinBackground(TRect /*aRect*/)
+ {
+ // Acquire background texture
+ const CHuiTexture* backgroundTexture = NULL;
+ TInt err = iEnv.Skin().GetTexture(EHuiSkinBackgroundTexture, backgroundTexture);
+ ASSERT(backgroundTexture!=NULL);
+ __ASSERT_ALWAYS(err == KErrNone, USER_INVARIANT());
+
+ // Apply background texture
+ THuiImage background(*backgroundTexture);
+
+ TPoint screenOrigin(0, 0);
+ iRenderSurface->GetScreenOrigin(screenOrigin);
+ // The origin is used to offset the background in the display's
+ // rendering surface, so that the background's origin is in the
+ // top left screen corner.
+ screenOrigin.iX = -screenOrigin.iX;
+ screenOrigin.iY = -screenOrigin.iY;
+
+ iGc->SetPenColor(KRgbWhite);
+ iGc->SetPenAlpha(255);
+ iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop);
+ iGc->Disable(CHuiGc::EFeatureBlending);
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ iGc->DrawImage(background, screenOrigin, background.Texture().Size());
+ }
+
+void CHuiDisplay::HWAcceleratedClearWithBackgroundItems(TRect aRect)
+ {
+ THuiDisplayBackgroundItem item;
+ CHuiS60Skin* s60skin = static_cast<CHuiS60Skin*>(&iEnv.Skin());
+ CHuiTexture* backgroundTexture = NULL;
+ for (TInt index = 0; index < iBackgroundItems.Count(); index++)
+ {
+ item = iBackgroundItems[index];
+ switch (item.ClearMode())
+ {
+ case EClearNone:
+ // do nothing...
+ break;
+ case EClearWithColor:
+ // do not draw anything if background item rect does not intersect with dirty/ current clip rect
+ if( item.Rect().Intersects(aRect))
+ {
+ iGc->SetPenColor(item.Color());
+ iGc->SetPenAlpha(255);
+ iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop);
+ iGc->Disable(CHuiGc::EFeatureBlending);
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ iGc->PushClip();
+ TRect temp = item.Rect();
+ temp.Intersection(aRect);
+ iGc->Clip(temp);
+ iGc->Clear();
+ iGc->PopClip();
+ }
+ break;
+ case EClearWithSkinBackground:
+ TRect skinRect;
+ TRect dummy;
+ GetRectForItem(item.SkinBackground(), dummy, skinRect);
+ backgroundTexture = s60skin->BackgroundTexture(item.SkinBackground());
+ if (backgroundTexture)
+ {
+ THuiImage background(*backgroundTexture);
+
+ TPoint screenOrigin(0, 0);
+ iRenderSurface->GetScreenOrigin(screenOrigin);
+ screenOrigin.iX = -screenOrigin.iX;
+ screenOrigin.iY = -screenOrigin.iY;
+ screenOrigin+=skinRect.iTl;
+
+ // do not draw anything if background item rects does not intersect with dirty/ current clip rect
+ skinRect.Intersection(item.Rect());
+ if( skinRect.Intersects(aRect) )
+ {
+ iGc->SetPenColor(KRgbWhite);
+ iGc->SetPenAlpha(255);
+ iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop);
+ iGc->Disable(CHuiGc::EFeatureBlending);
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ iGc->PushClip();
+ skinRect.Intersection(aRect);
+ iGc->Clip(skinRect);
+ iGc->DrawImage(background, screenOrigin, background.Texture().Size());
+ iGc->PopClip();
+ }
+ }
+ break;
+ }
+ }
+ }
+
+EXPORT_C void CHuiDisplay::SetVisibleAreaClippingRect(const TRect&
+ #ifndef SYMBIAN_BUILD_GCE
+ aVisibleAreaClippingRect
+ #endif
+ )
+ {
+// Visible area clipping is disabled in NGA
+#ifndef SYMBIAN_BUILD_GCE
+ iVisibleAreaClippingRect = aVisibleAreaClippingRect;
+#endif
+ }
+
+TRect CHuiDisplay::VisibleAreaClippingRect() const
+ {
+// Visible area clipping is disabled in NGA
+#ifndef SYMBIAN_BUILD_GCE
+ if (IsVisibleAreaClippingEnabled())
+ {
+ return iVisibleAreaClippingRect;
+ }
+ else
+ {
+ return VisibleArea();
+ }
+#else
+ return VisibleArea();
+#endif
+ }
+
+TBool CHuiDisplay::IsVisibleAreaClippingEnabled() const
+ {
+// Visible area clipping is disabled in NGA
+#ifndef SYMBIAN_BUILD_GCE
+ return iVisibleAreaClippingRect != TRect(0,0,0,0);
+#else
+ return EFalse;
+#endif
+ }
+
+void CHuiDisplay::ClipDirtyRect(TRect& aRect, TRect aClippingRect)
+ {
+ if (aRect.Intersects(aClippingRect))
+ {
+ aRect.Intersection(aClippingRect);
+ }
+ }
+
+EXPORT_C void CHuiDisplay::SetForegroundTexture(CHuiTexture* aTexture)
+ {
+ if (iForegroundTexture != aTexture)
+ {
+ delete iForegroundTexture;
+ iForegroundTexture = aTexture;
+ SetDirty();
+ }
+ }
+
+EXPORT_C CHuiTexture* CHuiDisplay::ForegroundTexture() const
+ {
+ return iForegroundTexture;
+ }
+
+
+void CHuiDisplay::DrawForegroundTexture()
+ {
+ if (iForegroundTexture)
+ {
+ // The following is similar to HWAcceleratedClearWithSkinBackground,
+ // except blending is enabled.
+
+ TPoint screenOrigin(0, 0);
+ iRenderSurface->GetScreenOrigin(screenOrigin);
+ screenOrigin.iX = -screenOrigin.iX;
+ screenOrigin.iY = -screenOrigin.iY;
+
+ THuiImage image = THuiImage(*iForegroundTexture);
+ iGc->SetPenColor(KRgbWhite);
+ iGc->SetPenAlpha(255);
+ iGc->SetAlign(EHuiAlignHLeft, EHuiAlignVTop);
+ iGc->Enable(CHuiGc::EFeatureBlending);
+ iGc->Enable(CHuiGc::EFeatureClipping);
+ iGc->DrawImage(image, screenOrigin, image.Texture().Size());
+ }
+ }
+
+EXPORT_C void CHuiDisplay::SetForegroundBitmapL(CFbsBitmap* aBitmap)
+ {
+ // Note this method may be called with same bitmap, e.g.
+ // when emulator display orientation is changed. Then we recreate
+ // device & context in order to avoid panics.
+
+ if ( !aBitmap )
+ {
+ delete iForegroundBitmapGc;
+ iForegroundBitmapGc = NULL;
+ delete iForegroundBitmapDevice;
+ iForegroundBitmapDevice = NULL;
+ iForegroundBitmap = NULL;
+ }
+ else
+ {
+ CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( aBitmap );
+ CleanupStack::PushL( device );
+
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError( device->CreateContext( gc ) );
+ User::LeaveIfNull( gc );
+
+ CleanupStack::Pop( device );
+
+ iForegroundBitmap = aBitmap;
+ delete iForegroundBitmapDevice;
+ iForegroundBitmapDevice = device;
+ delete iForegroundBitmapGc;
+ iForegroundBitmapGc = gc;
+ }
+ }
+
+EXPORT_C CFbsBitmap* CHuiDisplay::ForegroundBitmap() const
+ {
+ return iForegroundBitmap;
+ }
+