graphicsdeviceinterface/screendriver/swins/WINS.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <hal.h>
       
    17 #include <e32std.h>
       
    18 #include <stdlib.h>
       
    19 #include <bitdraw.h>
       
    20 #include "ScreenInfo.h"
       
    21 #include "_WININC.H"
       
    22 
       
    23 /**
       
    24 The max allowed screen number + 1.
       
    25 @internalComponent
       
    26 */
       
    27 const TInt KMaxScreenNumber = 32;
       
    28 
       
    29 /**
       
    30 TheWinsWindowHandlers array is used as a container for the created RWindows objects.
       
    31 Each RWindows object manages single Windows OS window, which can be shared between one
       
    32 or more Symbian OS devices.
       
    33 It cannot be a C++ array (some of the CArray... classes), because it is part of a shared
       
    34 global memory. If it is a C++ array, then its constructor will be called every time, when
       
    35 an exe loads scdv.dll, which means - the array data will be destroyed!
       
    36 @internalComponent
       
    37 */
       
    38 static RWindows* TheWinsWindowHandlers[KMaxScreenNumber];
       
    39 
       
    40 /**
       
    41 WindowHandler() global function is used to get a pointer to the RWindows object, responsible 
       
    42 for the drawing operations on the Emulator on the screen with aScreenNo number.
       
    43 @param aScreenNo Screen number
       
    44 @return A pointer to the related RWindows object or NULL if there is no such object.
       
    45 @panic "SCDV-13" panic if the aScreenNo is out of bounds [0..32].
       
    46 @see RPointerArray
       
    47 @internalComponent
       
    48 */
       
    49 RWindows* WindowHandler(TInt aScreenNo)
       
    50     {
       
    51     __ASSERT_ALWAYS(aScreenNo >= 0 && aScreenNo < KMaxScreenNumber, ::Panic(EScreenDriverPanicInvalidScreenNo));
       
    52     return TheWinsWindowHandlers[aScreenNo];
       
    53     }
       
    54 
       
    55 /**
       
    56 Used in CreateScreenSemaphoreName().
       
    57 @see CreateScreenSemaphoreName()
       
    58 @internalComponent
       
    59 */
       
    60 _LIT(KWindowInUseSemaphore,"WindowInUseSemaphore");
       
    61 
       
    62 /**
       
    63 This global function is used for the creation of the name of the semaphore, which helps
       
    64 RWindows functionality to detect the moment, when the related Windows OS window can be 
       
    65 destroyed safely - no more clients (Symbian OS screen devices).
       
    66 @param aScreenNo Screen number
       
    67 @param aScreenSemaphoreName An output parameter, where the semaphore name will be constructed
       
    68                             in the following format "WindowInUseSemaphore<ScreenNo>".
       
    69                             The length of aScreenSemaphoreName should be big enough for
       
    70                             the semaphore name.
       
    71 @internalComponent
       
    72 */
       
    73 void CreateScreenSemaphoreName(TInt aScreenNo, TDes& aScreenSemaphoreName)
       
    74     {
       
    75     aScreenSemaphoreName.Copy(KWindowInUseSemaphore);
       
    76     aScreenSemaphoreName.AppendNum(aScreenNo);
       
    77     }
       
    78 
       
    79 /**
       
    80 */
       
    81 RWindows::RWindows():
       
    82 	iHwnd(NULL),
       
    83 	iHdc(NULL),
       
    84 	iHbitmap(NULL),
       
    85 	iBitmapInfo(NULL),
       
    86 	iBitmapBits(NULL),
       
    87 	iH90bitmap(NULL),
       
    88 	i90BitmapInfo(NULL),
       
    89 	i90BitmapBits(NULL),
       
    90 	i90ByteWidth(0),
       
    91 	iByteWidth(0),
       
    92 	iEpocBitmapBits(NULL),
       
    93 	iOrientation(0),
       
    94     iScreenNo(-1)
       
    95 	{
       
    96     }
       
    97 
       
    98 /**
       
    99 The method returns a pointer to the RWindows object, which manages the Windows OS window
       
   100 for the aScreenNo Symbian OS device screen.
       
   101 If no RWindows object exists for the requested screen number, it will be created.
       
   102 @param aScreenNo Screen number
       
   103 @param aHwnd Windows OS - window handle
       
   104 @param aSize Screen size in pixels
       
   105 @return A pointer to the related for that screen number RWindows object or NULL if
       
   106         GetWindow() call fails. The reason for the failure can be: no memory or some
       
   107         Windows OS related problem.
       
   108 */
       
   109 RWindows* RWindows::GetWindow(TInt aScreenNo, TAny* aHwnd, const TSize& aSize)
       
   110 	{
       
   111     //If TheWinsWindowHandlers[aScreenNo] is not null, then it is a valid RWindows object, 
       
   112     //return it (a pointer to it).
       
   113     if(TheWinsWindowHandlers[aScreenNo])
       
   114         {
       
   115 		return TheWinsWindowHandlers[aScreenNo];
       
   116         }
       
   117     //TheWinsWindowHandlers[aScreenNo] is null - allocate a memory for it.
       
   118     //If the allocation fails - return NULL.
       
   119 	TheWinsWindowHandlers[aScreenNo] = (RWindows*)GlobalAlloc(GPTR,sizeof(RWindows));
       
   120 	if(!TheWinsWindowHandlers[aScreenNo])
       
   121         {
       
   122 		return NULL;
       
   123         }
       
   124     //Construct TheWinsWindowHandlers[aScreenNo] object, return NULL if the construction fails.
       
   125 	TRAPD(ret,TheWinsWindowHandlers[aScreenNo]->ConstructL(aHwnd,aSize));
       
   126 	if (ret != KErrNone)
       
   127 		{
       
   128 		TheWinsWindowHandlers[aScreenNo]->Destroy();
       
   129 		TheWinsWindowHandlers[aScreenNo] = NULL;
       
   130 		return NULL;
       
   131 		}
       
   132     //
       
   133     TheWinsWindowHandlers[aScreenNo]->iScreenNo = aScreenNo;
       
   134 	return TheWinsWindowHandlers[aScreenNo];
       
   135 	}
       
   136 
       
   137 /**
       
   138 The method releases the access the RWindows object, which manages aScreenNo screen.
       
   139 If there are no more clients (Symbian OS devices) for that window, it will be destroyed.
       
   140 @param aScreenNo Screen number
       
   141 */
       
   142 void RWindows::ReleaseWindow(TInt aScreenNo)
       
   143 	{
       
   144 	if(TheWinsWindowHandlers[aScreenNo] == NULL)
       
   145         {//The related TheWinsWindowHandlers[aScreenNo] is NULL, which means that the 
       
   146          //related RWindows object has been destroyed. Do nothing.
       
   147 		return;
       
   148         }
       
   149 	RSemaphore windowInUse;
       
   150     TBuf<32> screenSemaphoreName;
       
   151     ::CreateScreenSemaphoreName(aScreenNo, screenSemaphoreName);
       
   152 	TInt ret = windowInUse.OpenGlobal(screenSemaphoreName,EOwnerThread);
       
   153     //The related semaphore does not exist, which means - all the clients, which have a shared
       
   154     //access to aScreenNo screen, do not use it anymore. It is safe to destroy the related
       
   155     //Windows OS window object.
       
   156 	if (ret == KErrNotFound)
       
   157 		{
       
   158 		TheWinsWindowHandlers[aScreenNo]->Destroy();
       
   159 		TheWinsWindowHandlers[aScreenNo] = NULL;
       
   160 		}
       
   161 	windowInUse.Close();
       
   162 	}
       
   163 
       
   164 TUint8* RWindows::PixelAddress(TInt aX,TInt aY)
       
   165 	{
       
   166 	if (iOrientation & 1)
       
   167 		{
       
   168 		TUint8* pixelPtr = i90BitmapBits;
       
   169 		pixelPtr += i90ByteWidth * (i90BitmapInfo->bmiHeader.biHeight - aY - 1);
       
   170 		pixelPtr += aX * 3;
       
   171 		return pixelPtr;
       
   172 		}
       
   173 
       
   174 	TUint8* pixelPtr = iBitmapBits;
       
   175 	pixelPtr += iByteWidth * (iBitmapInfo->bmiHeader.biHeight - aY - 1);
       
   176 	pixelPtr += aX * 3;
       
   177 	return pixelPtr;
       
   178 	}
       
   179 
       
   180 
       
   181 	
       
   182 void RWindows::Destroy()
       
   183 	{
       
   184 	GdiFlush();
       
   185 	if (iHbitmap) DeleteObject(iHbitmap);
       
   186 	if (iH90bitmap) DeleteObject(iH90bitmap);
       
   187 	GlobalFree(iBitmapInfo);
       
   188 	GlobalFree(i90BitmapInfo);
       
   189 	if (iHwnd && iHdc) ReleaseDC(iHwnd,iHdc);
       
   190 	GlobalFree(iEpocBitmapBits);
       
   191 	GlobalFree(this);
       
   192 	}
       
   193 
       
   194 void RWindows::ConstructL(TAny* aHwnd,const TSize& aSize)
       
   195 	{
       
   196 	iHwnd = (HWND)aHwnd;
       
   197 	iHdc = GetDC(iHwnd);
       
   198 	User::LeaveIfNull(iHdc);
       
   199 	SetMapMode(iHdc,MM_TEXT);
       
   200 	SetROP2(iHdc,R2_COPYPEN);
       
   201 
       
   202 	iByteWidth = aSize.iWidth*3;
       
   203 	i90ByteWidth = aSize.iHeight*3;
       
   204 	TInt byteSize = aSize.iWidth * aSize.iHeight * 3;
       
   205 
       
   206 	iBitmapInfo = (BITMAPINFO*)User::LeaveIfNull(GlobalAlloc(GPTR,sizeof(BITMAPINFO)));
       
   207 	iBitmapInfo->bmiHeader.biBitCount = 24;
       
   208 	iBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
       
   209 	iBitmapInfo->bmiHeader.biWidth = aSize.iWidth;
       
   210 	iBitmapInfo->bmiHeader.biHeight = aSize.iHeight;
       
   211 	iBitmapInfo->bmiHeader.biPlanes = 1;
       
   212 	iBitmapInfo->bmiHeader.biCompression = BI_RGB;
       
   213 
       
   214 	i90BitmapInfo = (BITMAPINFO*)User::LeaveIfNull(GlobalAlloc(GPTR,sizeof(BITMAPINFO)));
       
   215 	i90BitmapInfo->bmiHeader.biBitCount = 24;
       
   216 	i90BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
       
   217 	i90BitmapInfo->bmiHeader.biWidth = aSize.iHeight;
       
   218 	i90BitmapInfo->bmiHeader.biHeight = aSize.iWidth;
       
   219 	i90BitmapInfo->bmiHeader.biPlanes = 1;
       
   220 	i90BitmapInfo->bmiHeader.biCompression = BI_RGB;
       
   221 
       
   222 	iHbitmap = CreateDIBSection(iHdc,iBitmapInfo,DIB_RGB_COLORS,(TAny**)&iBitmapBits,NULL,0);
       
   223 	User::LeaveIfNull(iHbitmap);
       
   224 	Mem::Fill(iBitmapBits,byteSize,0xff);
       
   225 	iH90bitmap = CreateDIBSection(iHdc,i90BitmapInfo,DIB_RGB_COLORS,(TAny**)&i90BitmapBits,NULL,0);
       
   226 	User::LeaveIfNull(iH90bitmap);
       
   227 	Mem::Fill(i90BitmapBits,byteSize,0xff);
       
   228 
       
   229 	//We have to allocate iEpocBitmapBits to be large enough to hold all color bytes (32 bpp)
       
   230 	//for the rectangle with aSize.iWidth & aSize.iHeight dimensions.
       
   231 	iEpocBitmapBits = (TUint32*)User::LeaveIfNull(GlobalAlloc(GMEM_FIXED,aSize.iWidth * aSize.iHeight * 4));
       
   232 	Mem::Fill(iEpocBitmapBits,aSize.iWidth * aSize.iHeight * 4,0xff);
       
   233 	}
       
   234 
       
   235 void RWindows::SetOrientation(TInt aOrientation)
       
   236 	{
       
   237 	iOrientation = aOrientation;
       
   238 	}
       
   239 
       
   240 TInt RWindows::Orientation() const
       
   241 	{
       
   242 	return iOrientation;
       
   243 	}
       
   244 
       
   245 void RWindows::Update(const TRegion& aRgn,const TSize& aSize)
       
   246 	{
       
   247 	if(aRgn.CheckError())
       
   248 		UpdateRect(TRect(aSize),aSize);
       
   249 	else
       
   250 		for(TInt count=0;count<aRgn.Count();count++)
       
   251 			UpdateRect(aRgn[count],aSize);
       
   252 	}
       
   253 
       
   254 void RWindows::UpdateRect(const TRect& aRect,const TSize& aSize)
       
   255 	{
       
   256 	if (iOrientation & 1)
       
   257 		SetDIBitsToDevice(iHdc,aRect.iTl.iX,aRect.iTl.iY,aRect.Width(),aRect.Height(),
       
   258 		aRect.iTl.iX,aSize.iWidth-aRect.iBr.iY,0,aSize.iWidth,i90BitmapBits,
       
   259 		((LPBITMAPINFO)i90BitmapInfo),DIB_RGB_COLORS);
       
   260 	else
       
   261 		SetDIBitsToDevice(iHdc,aRect.iTl.iX,aRect.iTl.iY,aRect.Width(),aRect.Height(),
       
   262 		aRect.iTl.iX,aSize.iHeight-aRect.iBr.iY,0,aSize.iHeight,iBitmapBits,
       
   263 		((LPBITMAPINFO)iBitmapInfo),DIB_RGB_COLORS);
       
   264 	}
       
   265 
       
   266 //Gets the Size dimension the RWindow is using as per orientation
       
   267 TSize RWindows::GetOrientedSize()
       
   268 	{
       
   269 	TSize orientedSize;
       
   270 	if (iOrientation&1)
       
   271 	orientedSize.SetSize(iEpocBitmapSize.iHeight,iEpocBitmapSize.iWidth);
       
   272 	else
       
   273 	orientedSize = iEpocBitmapSize;
       
   274 
       
   275 	return orientedSize;
       
   276 	}
       
   277 
       
   278 //Gets the actual orientation based refresh rect required from a 'physical' screen reference.
       
   279 TRect RWindows::GetOrientedRect(const TRect &aScreenRect)
       
   280 	{	
       
   281 	TRect orientedRect;	
       
   282 	
       
   283 	switch(iOrientation)		
       
   284 	{
       
   285 		case 1:
       
   286 			{
       
   287 			orientedRect.SetRect(aScreenRect.iTl.iY, 		
       
   288 								 iEpocBitmapSize.iWidth-aScreenRect.iBr.iX, 
       
   289 								 aScreenRect.iBr.iY,
       
   290 								 iEpocBitmapSize.iWidth-aScreenRect.iTl.iX);	
       
   291 			break;
       
   292 			}
       
   293 		case 2:
       
   294 			{	
       
   295 			orientedRect.SetRect(iEpocBitmapSize.iWidth-aScreenRect.iBr.iX,
       
   296 								 iEpocBitmapSize.iHeight-aScreenRect.iBr.iY, 							 
       
   297 								 iEpocBitmapSize.iWidth-aScreenRect.iTl.iX,
       
   298 								 iEpocBitmapSize.iHeight-aScreenRect.iTl.iY);
       
   299 			break;
       
   300 			}
       
   301 		case 3:
       
   302 		{
       
   303 			orientedRect.SetRect(iEpocBitmapSize.iHeight-aScreenRect.iBr.iY, 		
       
   304 								 aScreenRect.iTl.iX, 
       
   305 							 	 iEpocBitmapSize.iHeight-aScreenRect.iTl.iY,
       
   306 							 	 aScreenRect.iBr.iX);
       
   307 			break;
       
   308 		}		
       
   309 		default:
       
   310 		{
       
   311 			orientedRect = aScreenRect;
       
   312 			break;				
       
   313 		} 
       
   314 	}
       
   315 	
       
   316 	return orientedRect;	
       
   317 	}