graphicsdeviceinterface/screendriver/swins/SCDRAW.INL
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/screendriver/swins/SCDRAW.INL	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,235 @@
+// Copyright (c) 1997-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:
+//
+
+#include <hal.h>
+#include "_WININC.H"
+#include <bitdrawinterfaceid.h>
+
+#if defined(SYMBIAN_GRAPHICS_GCE)
+#include <surface.h>
+#endif //SYMBIAN_GRAPHICS_GCE
+
+template <class T> CScreenDevice<T>::~CScreenDevice()
+	{
+	iUpdateRegion.Close();
+	iWindowInUse.Close();
+	RWindows::ReleaseWindow(iScreenNo);
+	}
+
+/**
+Constructs the CScreenDevice<T> object.
+@param aScreenNo Screen number. It will be used in HAL::Get() calls.
+@param aHwnd Windows OS - window handle.
+@param aSize Screen size
+@return System-wide error codes, KErrNone if the construction was successfull.
+*/
+template <class T> TInt CScreenDevice<T>::ConstructScreen(TInt aScreenNo, TAny* aHwnd,const TSize& aSize)
+	{
+    iScreenNo = aScreenNo;
+	TInt ret = Construct(aSize);
+	if (ret != KErrNone)
+		return ret;
+
+	if (aSize.iWidth < aSize.iHeight)
+		{
+		TInt bpp = BitsPerPixel(iDispMode);
+		delete[] iScanLineBuffer;
+		TInt scanLineWords = ((iSize.iHeight * bpp) + 31) / 32;
+		iScanLineBuffer = (TUint32*)(User::Heap().Alloc(scanLineWords * 4));
+		if (!iScanLineBuffer)
+			return KErrNoMemory;
+		}
+
+	iWindow = RWindows::GetWindow(iScreenNo, aHwnd,aSize);
+	if (iWindow == NULL)
+		return KErrNoMemory;
+
+	SetBits(iWindow->EpocBitmapBits());
+    //Some explanations about iWindowInUse semaphore.
+    //On the Emulator, a single Windows OS window can be shared between many Symbian OS
+    //screen devices. iWindowInUse semaphore is used to help to determine the moment,
+    //when the related Windows OS window can be destroyed safely. Because it is a named
+    //semaphore, it will be created once by the first client (Symbian OS screen device)
+    //and opened (reference counted) by the every next client (Symbian OS screen device).
+    //In the CScreenDevice<T>'s deastructor iWindowInUse semaphore will be closed 
+    //(its reference counter gets decremented). When its value reaches zero, the Symbian OS
+    //will destroy the semaphore. This action will be detected by the RWindows::ReleaseWindow()'s
+    //implementation and the related Windows OS window will be destroyed.
+    TBuf<32> screenSemaphoreName;
+    ::CreateScreenSemaphoreName(iScreenNo, screenSemaphoreName);
+	ret = iWindowInUse.CreateGlobal(screenSemaphoreName,0,EOwnerThread);
+	if (ret == KErrAlreadyExists)
+        {
+		iWindowInUse.OpenGlobal(screenSemaphoreName,EOwnerThread);
+        }
+	return KErrNone;
+	}
+
+template <class T> TInt CScreenDevice<T>::HorzTwipsPerThousandPixels() const
+	{
+	if (iSize.iWidth==0)
+		return(0);
+	TInt twips = 0;
+	HAL::Get(iScreenNo, HALData::EDisplayXTwips,twips);
+	return twips * 1000 / iSize.iWidth;
+	}
+
+template <class T> TInt CScreenDevice<T>::VertTwipsPerThousandPixels() const
+	{
+	if (iSize.iHeight==0)
+		return(0);
+	TInt twips = 0;
+	HAL::Get(iScreenNo, HALData::EDisplayYTwips,twips);
+	return twips * 1000 / iSize.iHeight;
+	}
+
+template <class T> void CScreenDevice<T>::OrientationsAvailable(TBool aOrientation[4])
+	{
+	aOrientation[EOrientationNormal] = ETrue;
+	aOrientation[EOrientationRotated90] = ETrue;
+	aOrientation[EOrientationRotated180] = ETrue;
+	aOrientation[EOrientationRotated270] = ETrue;
+	}
+
+template <class T> void CScreenDevice<T>::SetDisplayMode(CFbsDrawDevice* aDrawDevice)
+	{
+	iUpdateRegion.Clear();
+	SetOrientation(static_cast<CFbsDrawDevice::TOrientation>(iWindow->Orientation()));
+	CopyOldSettings(aDrawDevice);
+	InitScreen();
+	}
+
+template <class T> void CScreenDevice<T>::SetAutoUpdate(TBool aAutoUpdate)
+	{
+	iAutoUpdate = aAutoUpdate;
+	}
+
+template <class T> void CScreenDevice<T>::SetScreenOrientation(TInt aOrientation)
+	{
+	Update();
+
+	TEmulatorFlip flip = EEmulatorFlipRestore;
+	switch (aOrientation)
+		{
+	case 0: // Already set
+		break;
+	case 1:
+		flip = EEmulatorFlipLeft;
+		break;
+	case 2:
+		flip = EEmulatorFlipInvert;
+		break;
+	case 3:
+		flip = EEmulatorFlipRight;
+		break;
+	default:
+		ASSERT(0);
+		break;
+		}
+	EmulatorFlip(flip, iScreenNo);
+	iWindow->SetOrientation(aOrientation);
+	}
+
+//
+// Update the screen with the update region.
+//
+template <class T> void CScreenDevice<T>::Update()
+	{
+	if (iUpdateRegion.IsEmpty())
+		return;
+	UpdateScreen(iUpdateRegion);
+	iUpdateRegion.Clear();
+	}
+
+//
+// Update the screen with the union of the update and specified regions.
+// aRegion - logical coordinates
+template <class T> void CScreenDevice<T>::Update(const TRegion& aRegion)
+	{
+	if(!aRegion.IsEmpty() && !aRegion.CheckError())
+		{
+		if(iScalingOff && iOriginIsZero)
+			{
+			iUpdateRegion.Union(aRegion);
+			}
+		else
+			{
+			register TInt rcCnt = aRegion.Count();
+			RRegion physRegion(rcCnt);
+			register TInt originX = iOrigin.iX;
+			register TInt originY = iOrigin.iY;
+			register TInt factorX = iScalingSettings.iFactorX;
+			register TInt factorY = iScalingSettings.iFactorY;
+			for(register TInt i=0;i<rcCnt;++i)
+				{
+				const TRect& logRect = aRegion[i];
+				TRect physRect; 
+				physRect.iTl.iX = ::Log2Phys(logRect.iTl.iX, originX, factorX, iSize.iWidth);
+				physRect.iTl.iY = ::Log2Phys(logRect.iTl.iY, originY, factorY, iSize.iHeight);
+				physRect.iBr.iX = ::RBtmLog2Phys(logRect.iBr.iX, originX, factorX, iSize.iWidth);
+				physRect.iBr.iY = ::RBtmLog2Phys(logRect.iBr.iY, originY, factorY, iSize.iHeight);
+				//The next statement sometimes have to allocate a block of memory and may
+				//fail setting RRegion's internal error flag. But there is nothing we can do.
+				physRegion.AddRect(physRect);
+				}
+			iUpdateRegion.Union(physRegion);
+			physRegion.Close();
+			}
+		}
+	Update();
+	}
+
+//
+// Update the update region.
+// aRect - logical coordinates
+template <class T> void CScreenDevice<T>::UpdateRegion(const TRect& aRect)
+	{
+	register TInt originX = iOrigin.iX;
+	register TInt originY = iOrigin.iY;
+	register TInt factorX = iScalingSettings.iFactorX;
+	register TInt factorY = iScalingSettings.iFactorY;
+	TRect physRect; 
+	physRect.iTl.iX = ::Log2Phys(aRect.iTl.iX, originX, factorX, iSize.iWidth);
+	physRect.iTl.iY = ::Log2Phys(aRect.iTl.iY, originY, factorY, iSize.iHeight);
+	physRect.iBr.iX = ::RBtmLog2Phys(aRect.iBr.iX, originX, factorX, iSize.iWidth);
+	physRect.iBr.iY = ::RBtmLog2Phys(aRect.iBr.iY, originY, factorY, iSize.iHeight);
+	physRect.Normalize();
+	iUpdateRegion.AddRect(physRect);
+	if(iUpdateRegion.Count() >= 10)
+		{
+		iUpdateRegion.AddRect(iUpdateRegion.BoundingRect());
+		}
+	if(iAutoUpdate)
+		{
+		Update();
+		}
+	}
+
+template <class T> void CScreenDevice<T>::UpdateScreen(const TRegion& aRegion)
+	{
+	if (aRegion.CheckError())
+		UpdateRect(iSize);
+	else
+		for(TInt count = 0; count < aRegion.Count(); count++)
+			UpdateRect(aRegion[count]);
+
+	iWindow->Update(aRegion,iSize);
+	}
+
+template <class T> TUint8* CScreenDevice<T>::WinPixelAddress(TInt aX,TInt aY) const
+	{
+	return iWindow->PixelAddress(aX,aY);
+	}
+