windowing/windowserver/tredir/redirector.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/tredir/redirector.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,374 @@
+// Copyright (c) 2006-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:
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code
+*/
+
+#include "redirector.h"
+#include <fbs.h>
+#include <bitdev.h>
+#include <bitstd.h>
+#include <gdi.h>
+#ifdef __WINS__
+#include "../debuglog/osbwin.h"
+#endif
+
+const TInt KDefaultScreen = 0;
+
+const TUint8 KCmdQuery			= 0;
+const TUint8 KCmdSetGcFront 	= 1;
+const TUint8 KCmdSetGcBack  	= 2;
+const TUint8 KCmdResetGcFront	= 3;
+const TUint8 KCmdResetGcBack 	= 4;
+const TUint8 KCmdSetBackObject 	= 5;
+const TUint8 KCmdResetBackObject= 6;
+
+const TUint8 KRedirectorInfoSig = 0x7e;
+
+NONSHARABLE_STRUCT(TRedirectorInfo)
+	{
+	TUint8 iSignature;
+	TAny* iFrontBufferInterface;
+	TAny* iBackBufferInterface;
+	TAny* iScreenConfigInterface;
+	TInt iScreenBitmapHandle;
+	TInt iFlickerBitmapHandle; 
+	TInt iUpdateCounter;
+	};
+
+NONSHARABLE_STRUCT(TWsBackBuffer): public MWsBackBuffer
+	{
+public:
+	TWsBackBuffer(CFbsBitmap* aBit,CFbsBitGc* aGc): iBit(aBit), iGc(aGc)
+		{}
+	virtual CFbsBitmap* GetBitmap() 
+		{return iBit;}
+	virtual CFbsBitGc* GetBitGc() 
+		{return iGc;}
+	virtual TInt SetBitGc(CFbsBitGc*)
+		{return KErrNotSupported;}
+	virtual TInt RedirectTo(MWsBackBuffer*)
+		{return KErrNotSupported;}
+	virtual void SetObserver(MWsFlickerFreeBufferObserver* /*aObserver*/)
+		{ASSERT(0);}
+	virtual MWsFlickerFreeBufferObserver* Observer()
+		{
+		 ASSERT(0);
+		 return NULL;
+		}
+	virtual CFbsBitGc* GetBitGcCurrent()
+		{
+		ASSERT(0);
+		return NULL;
+		}
+
+private:
+	CFbsBitmap* iBit;
+	CFbsBitGc* iGc;	
+	};
+
+//
+CWsGcRedirector* CWsGcRedirector::NewL()
+	{
+	return new(ELeave) CWsGcRedirector;	
+	}
+	
+CWsGcRedirector::~CWsGcRedirector()
+	{
+#ifdef __WINS__
+	delete iFrontWin;
+	delete iBackWin;
+	delete iUpdateDebugWinsTimer;
+#endif
+
+	if (iFrontBuf)
+		iFrontBuf->SetBitGc(NULL);
+	if (iBackBuf)
+		iBackBuf->SetBitGc(NULL);
+	
+	delete iFrontGc;
+	delete iFrontDev;
+	delete iFrontBit;
+	delete iBackGc;
+	delete iBackDev;
+	delete iBackBit;
+	delete iBadGc;
+	delete iBackObj;
+	}
+	
+void CWsGcRedirector::ConstructL(MWsGraphicDrawerEnvironment& aEnv, const TGraphicDrawerId& aId, MWsClient& aOwner, const TDesC8& aData)
+	{
+	BaseConstructL(aEnv, aId, aOwner);
+
+#ifdef __WINS__
+	if (aData.Length()>1)
+		iDisableWin = aData[1]==1;
+#endif
+	iScreenId = KDefaultScreen;
+	if (aData.Length()>0)
+		iScreenId = aData[0];
+	MWsScreen* scr = aEnv.Screen(iScreenId);
+	User::LeaveIfNull(scr);
+
+	MWsScreenConfig* cfg = scr->ObjectInterface<MWsScreenConfig>();
+	User::LeaveIfNull(cfg);
+
+	iFrontBuf = scr->ObjectInterface<MWsFrontBuffer>();
+	User::LeaveIfNull(iFrontBuf);
+	iBackBuf = scr->ObjectInterface<MWsBackBuffer>();
+	
+	iFrontBit = new(ELeave) CFbsBitmap;
+	iDefaultSize=cfg->SizeInPixels();
+	User::LeaveIfError(iFrontBit->Create(iDefaultSize,EColor64K));
+	iFrontDev = CFbsBitmapDevice::NewL(iFrontBit);
+	User::LeaveIfNull(iFrontDev);
+	User::LeaveIfError(iFrontDev->CreateContext(iFrontGc));
+	
+	User::LeaveIfError(iFrontDev->CreateContext(iBadGc));
+	iBadGc->ChangeDevice(NULL);
+
+#ifdef __WINS__
+	if (!iDisableWin)
+		{
+		iUpdateDebugWinsTimer = CPeriodic::NewL(0);
+		iUpdateDebugWinsTimer->Start(0, 300 * 1000, TCallBack(UpdateDebugWindowsCallback, this));
+
+		_LIT(KRedFront, "RedFront");
+		iFrontWin = CDebugOsbWin::NewL(KRedFront, iFrontBit->SizeInPixels());
+		}
+#endif	
+
+	if (iBackBuf)
+		{
+		CFbsBitmap* bit = iBackBuf->GetBitmap();
+		User::LeaveIfNull(bit);
+		iBackBit = new(ELeave) CFbsBitmap;
+		User::LeaveIfError(iBackBit->Create(bit->SizeInPixels(),EColor64K));
+		iBackDev = CFbsBitmapDevice::NewL(iBackBit);
+		User::LeaveIfNull(iBackDev);
+		User::LeaveIfError(iBackDev->CreateContext(iBackGc));
+		
+		iBackObj = new(ELeave) TWsBackBuffer(iBackBit,iBackGc);
+#ifdef __WINS__		
+		if (!iDisableWin)
+			{
+			_LIT(KRedBack, "RedBack");
+			iBackWin = CDebugOsbWin::NewL(KRedBack, iBackBit->SizeInPixels());
+			}
+#endif		
+		}
+		
+	// compile check, non-const interface access
+	MWsGraphicDrawerEnvironment& ee = Env();
+	MWsScreen* ss = ee.Screen(iScreenId);
+	MWsScreenConfig* cc = ss->ObjectInterface<MWsScreenConfig>();
+	}
+
+void CWsGcRedirector::HandleMessage(const TDesC8& aData)
+	{
+	// wserv already check data size, and won't invoke this handler if it's empty
+	TBuf8<1> ack;
+	ack.Append(KRedirectorInfoSig);
+	
+	switch (aData[0])
+		{
+		case KCmdQuery:
+		SendInfo();
+		break;
+		
+		case KCmdSetGcFront:
+		Env().RegisterEventHandler(this,this,TWservCrEvent::EScreenUpdated|TWservCrEvent::EScreenOrientationChanged|TWservCrEvent::EDeviceOrientationChanged);
+
+		// -test bad gc
+		__ASSERT_ALWAYS(iFrontBuf->SetBitGc(iBadGc)==KErrArgument, User::Invariant());	
+		// -test bad gc
+		__ASSERT_ALWAYS(iFrontBuf->SetBitGc(iBadGc,ETrue)==KErrArgument, User::Invariant());
+		// +test
+		__ASSERT_ALWAYS(iFrontBuf->SetBitGc(iFrontGc,EFalse)==KErrNone, User::Invariant());
+		// -test duplicate calls
+		__ASSERT_ALWAYS(iFrontBuf->SetBitGc(iFrontGc)==KErrAlreadyExists, User::Invariant());
+		
+		SendMessage(ack);
+		break;
+		
+		case KCmdSetGcBack:
+		if (iBackBuf)
+			{
+			// -test bad gc
+			__ASSERT_ALWAYS(iBackBuf->SetBitGc(iBadGc)==KErrArgument, User::Invariant());
+			// +test
+			__ASSERT_ALWAYS(iBackBuf->SetBitGc(iBackGc)==KErrNone, User::Invariant());
+			// -test duplicate calls
+			__ASSERT_ALWAYS(iBackBuf->SetBitGc(iBackGc)==KErrAlreadyExists, User::Invariant());
+			// -test double redirection
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(iBackObj)==KErrInUse, User::Invariant());
+			}
+		SendMessage(ack);
+		break;
+		
+		case KCmdResetGcFront:
+		Env().UnregisterEventHandler(this);
+		iUpdateCounter = 0;
+
+		__ASSERT_ALWAYS(iFrontBuf->SetBitGc(NULL,EFalse)==KErrNone, User::Invariant());
+		// -test duplicate calls
+		__ASSERT_ALWAYS(iFrontBuf->SetBitGc(NULL,EFalse)==KErrNone, User::Invariant());
+		SendMessage(ack);
+		break;
+		
+		case KCmdResetGcBack:
+		if (iBackBuf)
+			{
+			// +test
+			__ASSERT_ALWAYS(iBackBuf->SetBitGc(NULL)==KErrNone, User::Invariant());
+			// -test duplicate calls
+			__ASSERT_ALWAYS(iBackBuf->SetBitGc(NULL)==KErrNone, User::Invariant());
+			}
+		SendMessage(ack);
+		break;
+
+		case KCmdSetBackObject:
+		if (iBackBuf)
+			{
+			TWsBackBuffer badObj1(NULL,iBackGc);
+			// -test bad obj (null bitmap)
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(&badObj1)==KErrArgument, User::Invariant());
+			// -test bad obj (null gc)
+			TWsBackBuffer badObj2(iBackBit,NULL);
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(&badObj2)==KErrArgument, User::Invariant());			
+			// -test bad obj (null device)
+			TWsBackBuffer badObj3(iBackBit,iBadGc);			
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(&badObj3)==KErrArgument, User::Invariant());
+			// +test
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(iBackObj)==KErrNone, User::Invariant());
+			// -test duplicate calls
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(iBackObj)==KErrAlreadyExists, User::Invariant());
+			// -test double redirection
+			__ASSERT_ALWAYS(iBackBuf->SetBitGc(iBackGc)==KErrInUse, User::Invariant());
+			}
+		SendMessage(ack);
+		break;
+
+		case KCmdResetBackObject:
+		if (iBackBuf)
+			{
+			// +test
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(NULL)==KErrNone, User::Invariant());
+			// -test duplicate calls
+			__ASSERT_ALWAYS(iBackBuf->RedirectTo(NULL)==KErrNone, User::Invariant());
+			}
+		SendMessage(ack);
+		break;
+		}
+	}
+	
+void CWsGcRedirector::DoDraw(MWsGc& aGc, const TRect& aRect, const TDesC8& aData) const
+	{
+	aGc.PushBitGcSettings();
+	CFbsBitGc& bc = aGc.BitGc();	
+	bc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+	bc.SetBrushColor(TRgb(255,0,0,128));
+	bc.DrawRect(aRect);
+	TGraphicDrawerId id;
+	id.iId = 0x10281fb6;
+	id.iIsUid = ETrue;
+	const CWsGraphicDrawer* listener = Env().ResolveGraphic(id);
+	if (listener)
+		listener->Draw(aGc, aRect, aData);
+	aGc.PopBitGcSettings();
+	
+	// compile check, const interface access
+	const MWsGraphicDrawerEnvironment& env = Env(); // Env() const
+	const MWsScreen* scr = env.Screen(iScreenId); // Screen(TInt) const
+	const MWsScreenConfig* cfg = scr->ObjectInterface<MWsScreenConfig>(); // ObjectInterface() const
+	}
+
+void CWsGcRedirector::SendInfo()
+	{
+	TPckgBuf<TRedirectorInfo> buf;
+	MWsScreen* scr = Env().Screen(iScreenId);
+	if (scr)
+		{
+		buf().iSignature = KRedirectorInfoSig;
+		buf().iFrontBufferInterface = scr->ObjectInterface<MWsFrontBuffer>();
+		buf().iBackBufferInterface = scr->ObjectInterface<MWsBackBuffer>();
+		buf().iScreenConfigInterface = scr->ObjectInterface<MWsScreenConfig>();
+		buf().iScreenBitmapHandle = iFrontBit->Handle();
+		buf().iFlickerBitmapHandle = iBackBit? iBackBit->Handle() : 0;
+		buf().iUpdateCounter = iUpdateCounter;
+		}
+	TInt err = SendMessage(buf);
+	__ASSERT_ALWAYS(err>=KErrNone, User::Invariant());
+	}
+
+void CWsGcRedirector::DoHandleEvent(const TWservCrEvent& aEvent)
+	{
+	if (aEvent.ScreenNumber()==iScreenId)
+		{
+		switch(aEvent.Type())
+			{
+		case TWservCrEvent::EScreenUpdated:
+			++iUpdateCounter;
+			break;
+		case TWservCrEvent::EDeviceOrientationChanged:
+		case TWservCrEvent::EScreenOrientationChanged:
+			{
+			CFbsBitGc::TGraphicsOrientation orientation=aEvent.Orientation();
+			TSize bmpSize;
+			if (orientation==CFbsBitGc::EGraphicsOrientationNormal || orientation==CFbsBitGc::EGraphicsOrientationRotated180)
+				bmpSize=iDefaultSize;
+			else
+				bmpSize.SetSize(iDefaultSize.iHeight,iDefaultSize.iWidth);
+			const TSize fBufSize(iFrontBit->SizeInPixels());
+			if (fBufSize!=bmpSize)
+				{
+				__ASSERT_DEBUG(fBufSize.iWidth==bmpSize.iHeight && fBufSize.iHeight==bmpSize.iWidth, User::Invariant());
+				iFrontDev->SwapWidthAndHeight();
+				iFrontGc->Activate(iFrontDev);
+				}
+			}
+			break;
+			}
+		}
+	}
+
+#ifdef __WINS__
+TInt CWsGcRedirector::UpdateDebugWindowsCallback(TAny* aSelf)
+	{
+	CWsGcRedirector* self = static_cast<CWsGcRedirector*>(aSelf);
+	if(!self)
+		return KErrArgument;
+
+	if(self->iFrontWin && self->iFrontBit)
+		{
+		CFbsBitmap* bitmap = self->iFrontBit;
+		bitmap->LockHeap();
+		self->iFrontWin->Refresh(bitmap->SizeInPixels(), bitmap->DisplayMode(), bitmap->DataAddress());
+		bitmap->UnlockHeap();
+		}
+
+	if(self->iBackWin && self->iBackBit)
+		{
+		CFbsBitmap* bitmap = self->iBackBit;
+		bitmap->LockHeap();
+		self->iBackWin->Refresh(bitmap->SizeInPixels(), bitmap->DisplayMode(), bitmap->DataAddress());
+		bitmap->UnlockHeap();
+		}
+	return KErrNone;
+	}
+#endif