sl@0: // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include "offscreenbitmap.h"
sl@0: #include "inifile.h"
sl@0: #include "panics.h"
sl@0: #include "ScrDev.H"
sl@0: #include "server.h"
sl@0: #include "wstop.h"
sl@0: #include "rootwin.h"
sl@0: #if defined(__WINS__) && defined(_DEBUG)
sl@0: #include "../../debuglog/osbwin.h"
sl@0: #endif
sl@0: 
sl@0: GLREF_D TDisplayMode ParseDisplayMode(const TDesC& aModeName);
sl@0: 
sl@0: CWsOffScreenBitmap* CWsOffScreenBitmap::NewL(CScreen* aScreen)
sl@0: 	{
sl@0: 	CWsOffScreenBitmap* self=new(ELeave) CWsOffScreenBitmap(aScreen);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: inline CWsOffScreenBitmap::CWsOffScreenBitmap(CScreen* aScreen) :iScreen(aScreen)
sl@0: 	{}
sl@0: 
sl@0: CWsOffScreenBitmap::~CWsOffScreenBitmap()
sl@0: 	{
sl@0: 	delete iBitmapGc;
sl@0: 	delete iBitmap;
sl@0: 	iObserver = NULL;
sl@0: #if defined(__WINS__) && defined(_DEBUG)
sl@0: 	delete iOsbWin;
sl@0: #endif
sl@0: 	delete iBitmapDevice;	
sl@0: 	}
sl@0: 
sl@0: template <class T> 
sl@0: LOCAL_C inline void Swap(T& aLeft, T& aRight)
sl@0: 		{ T temp=aLeft;aLeft=aRight;aRight=temp;}
sl@0: template <class T> 
sl@0: LOCAL_C inline TBool SwapIfLeftIsBigger(T& aLeft, T& aRight)
sl@0: 		{if (aLeft>aRight) { ::Swap(aLeft, aRight); return (aRight>aLeft);} return (aLeft>aRight);}
sl@0: 
sl@0: void CWsOffScreenBitmap::ConstructL()
sl@0: 	{
sl@0: 	_LIT(KFlickerBufferMode,"FLICKERBUFFERMODE");
sl@0: 	TPtrC flickerBufferModeName;
sl@0: 	TDisplayMode displayMode = ENone;
sl@0: 	if (WsIniFile->FindVar(iScreen->ScreenNumber(), KFlickerBufferMode, flickerBufferModeName))
sl@0: 		displayMode = ParseDisplayMode(flickerBufferModeName);
sl@0: 	if (displayMode == ENone)
sl@0: 		displayMode = iScreen->DisplayMode();
sl@0: 	
sl@0: 	WS_ASSERT_DEBUG(displayMode!=ENone, EWsPanicNoDisplayModeFound);
sl@0: 	iBitmap=new(ELeave) CFbsBitmap;
sl@0: 	TSize screenSize=iScreen->ScreenDevice()->SizeInPixels();
sl@0: 	TBool haveSwapped=SwapIfLeftIsBigger(screenSize.iWidth, screenSize.iHeight);
sl@0: 	User::LeaveIfError(iBitmap->Create(screenSize,displayMode));
sl@0: 	if (haveSwapped)
sl@0: 		{
sl@0: 		iBitmap->SwapWidthAndHeight();
sl@0: 		}
sl@0: 	User::LeaveIfError(iBitmap->SetDisplayMode(iScreen->DisplayMode()));
sl@0: 	iBitmapDevice=CFbsBitmapDevice::NewL(iBitmap);
sl@0: 	User::LeaveIfError(iBitmapDevice->CreateContext(iBitmapGc));
sl@0: 	
sl@0: 	TSizeMode sizeMode = iScreen->ScreenSizeModeData(iScreen->ScreenSizeMode());
sl@0: 	TSize osbSize(iBitmap->SizeInPixels());
sl@0: 	TSize osbTwips(sizeMode.iScreenTwipsSize);
sl@0: 	if (osbSize!=sizeMode.iScreenSize)
sl@0: 		{
sl@0: 		// The specified screen twips size is for the specified screen pixel size, however the OSB
sl@0: 		// is potentially larger as it needs to hold the maximum possible screen size, so we need
sl@0: 		// to scale the twips size up correspondingly.
sl@0: 		osbTwips.iWidth=sizeMode.iScreenTwipsSize.iWidth*osbSize.iWidth/sizeMode.iScreenSize.iWidth;
sl@0: 		osbTwips.iHeight=sizeMode.iScreenTwipsSize.iHeight*osbSize.iHeight/sizeMode.iScreenSize.iHeight;
sl@0: 		}
sl@0: 	iBitmap->SetSizeInTwips(osbTwips);
sl@0: 	
sl@0: #	if defined(__WINS__) && defined(_DEBUG)
sl@0: 	_LIT(KDebugOsb,"DEBUGOSB");
sl@0: 	if (WsIniFile->FindVar(iScreen->ScreenNumber(),KDebugOsb))
sl@0: 		{
sl@0: 		_LIT(KDebugOsbTitleFormat, "Screen %d, offscreen bitmap");
sl@0: 		TBuf<32> title;
sl@0: 		title.Format(KDebugOsbTitleFormat, iScreen->ScreenNumber());
sl@0: 		iOsbWin = CDebugOsbWin::NewL(title, iBitmap->SizeInPixels());
sl@0: 		}
sl@0: #	endif
sl@0: 	}
sl@0: 
sl@0: TInt CWsOffScreenBitmap::DisplayModeChanged(TBool aSwapWidthAndHeight)
sl@0: 	{
sl@0: 	TInt err=KErrNone;
sl@0: 	if (aSwapWidthAndHeight)
sl@0: 		{
sl@0: 		err=iBitmapDevice->SwapWidthAndHeight();
sl@0: 		WS_ASSERT_DEBUG(err==KErrNone, EWsCreatedOffScreenBitmapInWrongDimensions);
sl@0: 		iBitmapGc->Activate(iBitmapDevice);
sl@0: 		}
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: void CWsOffScreenBitmap::SetObserver(MWsFlickerFreeBufferObserver* aObserver)
sl@0: 	{
sl@0: 	iObserver = aObserver;
sl@0: 	}
sl@0: 
sl@0: MWsFlickerFreeBufferObserver * CWsOffScreenBitmap::Observer()
sl@0: 	{
sl@0: 	return iObserver;
sl@0: 	}
sl@0: 
sl@0: CFbsBitmap* CWsOffScreenBitmap::Bitmap()
sl@0: 	{
sl@0: 	CFbsBitmap* bmp = iRedirectBuffer? iRedirectBuffer->GetBitmap() : iBitmap;
sl@0: 	WS_ASSERT_DEBUG(bmp!=NULL, EWsPanicTemp);
sl@0: 	return bmp;
sl@0: 	}
sl@0: 
sl@0: CFbsDevice* CWsOffScreenBitmap::BitmapDevice()
sl@0: 	{
sl@0: 	CFbsDevice* device = static_cast<CFbsDevice*>(GetBitGcCurrent()->Device());
sl@0: 	WS_ASSERT_DEBUG(device!=NULL, EWsPanicNullDeviceHandle);
sl@0: 	return device;
sl@0: 	}
sl@0: 
sl@0: // This function updates the OffScreenBitmap and TransparencyManager's device and GC
sl@0: // Note: Here the OffScreenBitmap's scale is not considered.
sl@0: void CWsOffScreenBitmap::UpdateGc(const TBool aSwapWidthAndHeight)
sl@0: 	{
sl@0: 	if (aSwapWidthAndHeight)
sl@0: 		{
sl@0: 		iBitmapDevice->SwapWidthAndHeight();
sl@0: 		}
sl@0: 	iBitmapDevice->SetScalingFactor(iScreen->CurrentScreenModeScaledOrigin(),1,1,1,1);
sl@0: 	iBitmapGc->Activate(iBitmapDevice);
sl@0: 	}
sl@0: 
sl@0: #if defined(__WINS__) && defined(_DEBUG)
sl@0: void CWsOffScreenBitmap::Update()
sl@0: 	{
sl@0: 	if (iOsbWin)
sl@0: 		{
sl@0: 		iBitmap->LockHeap();
sl@0: 		iOsbWin->Refresh(iBitmap->SizeInPixels(), iBitmap->DisplayMode(), iBitmap->DataAddress());
sl@0: 		iBitmap->UnlockHeap();
sl@0: 		}
sl@0: 	}
sl@0: #endif
sl@0: 
sl@0: /**
sl@0:  Implementing MWsBackBuffer interface
sl@0: */
sl@0: CFbsBitmap* CWsOffScreenBitmap::GetBitmap()
sl@0: 	{
sl@0: 	return iBitmap;
sl@0: 	}
sl@0: 
sl@0: CFbsBitGc* CWsOffScreenBitmap::GetBitGc()
sl@0: 	{
sl@0: 	return iBitmapGc;
sl@0: 	}
sl@0: 
sl@0: CFbsBitGc* CWsOffScreenBitmap::GetBitGcCurrent()
sl@0: 	{
sl@0: 	CFbsBitGc* gc = iRedirectGc? iRedirectGc : (iRedirectBuffer? iRedirectBuffer->GetBitGc() : iBitmapGc);
sl@0: 	WS_ASSERT_DEBUG(gc!=NULL, EWsPanicTemp);
sl@0: 	return gc;
sl@0: 	}
sl@0: 	
sl@0: TInt CWsOffScreenBitmap::SetBitGc(CFbsBitGc* aBitGc)
sl@0: 	{
sl@0: 	if (iRedirectBuffer)
sl@0: 		return KErrInUse;
sl@0: 
sl@0: 	if (aBitGc && (aBitGc==iBitmapGc || aBitGc==iRedirectGc))
sl@0: 		return KErrAlreadyExists;
sl@0: 	
sl@0: 	if (aBitGc && !aBitGc->Device())
sl@0: 		return KErrArgument;
sl@0: 	
sl@0: 	iRedirectGc = aBitGc;
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: TInt CWsOffScreenBitmap::RedirectTo(MWsBackBuffer* aTarget)
sl@0: 	{
sl@0: 	if (iRedirectGc)
sl@0: 		return KErrInUse;
sl@0: 
sl@0: 	if (aTarget && aTarget==iRedirectBuffer)
sl@0: 		return KErrAlreadyExists;
sl@0: 	
sl@0: 	if ( aTarget && iScreen->HasVisibleDirectOnQueue() )
sl@0: 		return KErrInUse;	
sl@0: 	if (aTarget && 
sl@0: 			(
sl@0: 			!aTarget->GetBitmap()|| 
sl@0: 			!aTarget->GetBitGc() || 
sl@0: 			(aTarget->GetBitGc() && !aTarget->GetBitGc()->Device())
sl@0: 			)
sl@0: 		)
sl@0: 		return KErrArgument;
sl@0: 
sl@0: 	iRedirectBuffer = aTarget;
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: TAny* CWsOffScreenBitmap::ResolveObjectInterface(TUint aTypeId)
sl@0: 	{
sl@0: 	switch (aTypeId)
sl@0: 		{
sl@0: 		case MWsBackBuffer::EWsObjectInterfaceId:
sl@0: 			return static_cast<MWsBackBuffer *>(this);
sl@0: 		}
sl@0: 	return NULL;
sl@0: 	}