os/graphics/windowing/windowserver/debuglog/osbwin.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-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 // Win32 dependent code for debugging wserv offscreenbuffer and UI surface on emulator
    17 //
    18 #include "osbwin.h"
    19 #include "_windows.h"
    20 
    21 TInt CDebugOsbWin::iId=0;
    22 const TInt KMaxBuffer=32;
    23 HBITMAP* TheBitmap[KMaxBuffer];
    24 HWND* TheWindow[KMaxBuffer];
    25 
    26 // Application window specific messages
    27 #define WMA_RESIZE		(WM_APP + 0)
    28 
    29 struct TWin32Info
    30 	{
    31 	HWND iHwnd;
    32 	HDC iHdc;
    33 	HBITMAP iHbitmap;
    34 	BITMAPINFO* iBitmapInfo;
    35 	};
    36 
    37 EXPORT_C CDebugOsbWin* CDebugOsbWin::NewL(const TDesC& aName, TSize aSize)
    38 	{
    39 	CDebugOsbWin* self = new(ELeave) CDebugOsbWin(aName, aSize);
    40 	CleanupStack::PushL(self);
    41 	self->ConstructL();
    42 	CleanupStack::Pop(self);
    43 	return self;
    44 	}
    45 
    46 CDebugOsbWin::CDebugOsbWin(const TDesC& aName, TSize aSize):
    47 	iThreadCreated(EFalse), iSize(aSize), iName(aName)
    48 	{}
    49 
    50 EXPORT_C CDebugOsbWin::~CDebugOsbWin()
    51 	{
    52 	iSem.Close();
    53 	if (iThreadCreated)
    54 		{
    55 		iThread.Terminate(0);
    56 		iThread.Close();
    57 		}
    58 	if (iWin32)
    59 		{
    60 		if (iWin32->iHbitmap)
    61 			DeleteObject(iWin32->iHbitmap);
    62 		if (iWin32->iBitmapInfo)
    63 			User::Free(iWin32->iBitmapInfo);
    64 		if (iWin32->iHwnd && iWin32->iHdc)
    65 			ReleaseDC(iWin32->iHwnd,iWin32->iHdc);
    66 		delete iWin32;
    67 		}
    68 	if (iPalette)
    69 		delete iPalette;
    70 	--CDebugOsbWin::iId;
    71 	}
    72 
    73 void CDebugOsbWin::ConstructL()
    74 	{
    75 	if (iId>=KMaxBuffer)
    76 		User::Leave(KErrNoMemory);
    77 	iPalette=CPalette::NewDefaultL(EColor256);
    78 	iWin32=new(ELeave) TWin32Info;
    79 	// store window handle and bitmap association to global table
    80 	TheWindow[iId]=&(iWin32->iHwnd);
    81 	TheBitmap[iId]=&(iWin32->iHbitmap);
    82 
    83 	_LIT(KIdFormat, " (%d)");
    84 	iName.AppendFormat(KIdFormat, iId);
    85 
    86 	++iId;
    87 	iSem.CreateLocal(0);
    88 	const TInt KHeapSize=0x4000;
    89 	User::LeaveIfError(iThread.Create(iName,CDebugOsbWin::ThreadMain,KDefaultStackSize,KHeapSize,KHeapSize,this));
    90 	iThread.SetPriority(EPriorityMuchLess);
    91 	iThread.Resume();
    92 	iThreadCreated=ETrue;
    93 	iSem.Wait();
    94 	// iHwnd initialized by WinMain
    95 	iWin32->iHdc=GetDC(iWin32->iHwnd);
    96 	SetMapMode(iWin32->iHdc,MM_TEXT);
    97 	SetROP2(iWin32->iHdc,R2_COPYPEN);
    98 	TInt byteSize=iSize.iWidth*iSize.iHeight*3;
    99 	iWin32->iBitmapInfo=(BITMAPINFO*)User::Alloc(sizeof(BITMAPINFO));
   100 	User::LeaveIfNull(iWin32->iBitmapInfo);
   101 	iWin32->iBitmapInfo->bmiHeader.biBitCount=24;
   102 	iWin32->iBitmapInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
   103 	iWin32->iBitmapInfo->bmiHeader.biWidth=iSize.iWidth;
   104 	iWin32->iBitmapInfo->bmiHeader.biHeight=-iSize.iHeight;//top-down DIB
   105 	iWin32->iBitmapInfo->bmiHeader.biPlanes=1;
   106 	iWin32->iBitmapInfo->bmiHeader.biCompression=BI_RGB;
   107 	iWin32->iHbitmap=CreateDIBSection(iWin32->iHdc,iWin32->iBitmapInfo,DIB_RGB_COLORS,(TAny**)&iBitmapBits,NULL,0);
   108 	User::LeaveIfNull(iWin32->iHbitmap);
   109 	Mem::Fill(iBitmapBits,byteSize,0xff);
   110 	}
   111 
   112 EXPORT_C void CDebugOsbWin::Refresh(TSize aSize, TDisplayMode aDisplayMode, const TUint32* aDataAddress)
   113 	{
   114 	TBool hasResized = EFalse;
   115 
   116 	// When screen is rotated, the size can change as width and height are swapped.
   117 	if (iSize != aSize)
   118 		{
   119 		iSize = aSize;
   120 		iWin32->iBitmapInfo->bmiHeader.biWidth = aSize.iWidth;
   121 		iWin32->iBitmapInfo->bmiHeader.biHeight = -aSize.iHeight; //top-down DIB
   122 		hasResized = ETrue;
   123 		}
   124 
   125 	switch (aDisplayMode)
   126 		{
   127 		case EGray4:
   128 			Copy2Bpp(aDataAddress);
   129 			break;
   130 		case EColor256:
   131 			Copy8Bpp(aDataAddress);
   132 			break;
   133 		case EColor4K:
   134 			Copy12Bpp(aDataAddress);
   135 			break;
   136 		case EColor64K:
   137 			Copy16Bpp(aDataAddress);
   138 			break;
   139 		case EColor16M:
   140 			Copy24Bpp(aDataAddress);
   141 			break;
   142 		case EColor16MU:
   143 		case EColor16MA:
   144 		case EColor16MAP:	// Should really have alpha divided out
   145 			CopyU24Bpp(aDataAddress);
   146 			break;
   147 		default:
   148 			return;
   149 		}
   150 	SetDIBitsToDevice(iWin32->iHdc,0,0,iSize.iWidth,iSize.iHeight,0,0,0,iSize.iHeight,iBitmapBits,
   151 		((LPBITMAPINFO)iWin32->iBitmapInfo),DIB_RGB_COLORS);
   152 	if (hasResized)
   153 		{
   154 		// This will cause a redraw so no need to invalidate.
   155 		PostMessage(iWin32->iHwnd, WMA_RESIZE, iSize.iWidth + iHExtra, iSize.iHeight + iVExtra);
   156 		}
   157 	else
   158 		{
   159 		InvalidateRect(iWin32->iHwnd,NULL,FALSE);
   160 		}
   161 	}
   162 
   163 void CDebugOsbWin::Copy2Bpp(const TUint32* aDataAddress)
   164 	{
   165 	const TUint8 gray[]={0,85,170,255};
   166 	
   167 	const TUint8* src=(const TUint8*)aDataAddress;
   168 	TUint8* dest=iBitmapBits;
   169 	const TInt width=iSize.iWidth>>2;
   170 	for (TInt row=0;row<iSize.iHeight;++row)
   171 		{
   172 		for (TInt col=0;col<width;++col)
   173 			{
   174 			TUint8 p1=*src++;
   175 			TUint8 p2=TUint8((p1>>2) & 0x03);
   176 			TUint8 p3=TUint8((p1>>4) & 0x03);
   177 			TUint8 p4=TUint8((p1>>6) & 0x03);
   178 			p1&=0x03;
   179 			dest[0]=dest[1]=dest[2]=gray[p1];
   180 			dest[3]=dest[4]=dest[5]=gray[p2];
   181 			dest[6]=dest[7]=dest[8]=gray[p3];
   182 			dest[9]=dest[10]=dest[11]=gray[p4];
   183 			dest+=12; // 1 byte source equals to 4 destination pixels
   184 			}
   185 		}
   186 	}
   187 
   188 void CDebugOsbWin::Copy8Bpp(const TUint32* aDataAddress)
   189 	{
   190 	if (!iPalette)
   191 		return;
   192 	const TUint8* src=(const TUint8*)aDataAddress;
   193 	TUint8* dest=iBitmapBits;
   194 	for (TInt row=0;row<iSize.iHeight;++row)
   195 		{
   196 		for (TInt col=0;col<iSize.iWidth;++col)
   197 			{
   198 			const TRgb rgb(iPalette->GetEntry(*src++));
   199 			dest[0]=TUint8(rgb.Blue());
   200 			dest[1]=TUint8(rgb.Green());
   201 			dest[2]=TUint8(rgb.Red());
   202 			dest+=3;
   203 			}
   204 		}
   205 	}
   206 
   207 void CDebugOsbWin::Copy12Bpp(const TUint32* aDataAddress)
   208 	{
   209 
   210 	const TUint16* src=(const TUint16*)aDataAddress;
   211 	TUint8* dest=iBitmapBits;
   212 	for (TInt row=0;row<iSize.iHeight;++row)
   213 		{
   214 		for (TInt col=0;col<iSize.iWidth;++col)
   215 			{
   216 			dest[0]=TUint8((*src & 0x00f));
   217 			dest[0]|=dest[0] << 4;
   218 			dest[1]=TUint8((*src & 0x0f0));
   219 			dest[1]|=dest[1] >> 4;
   220 			dest[2]=TUint8((*src & 0xf00)>>4);
   221 			dest[2]|=dest[2] >> 4;
   222 			++src;
   223 			dest+=3;
   224 			}
   225 		}
   226 	}
   227 
   228 void CDebugOsbWin::Copy16Bpp(const TUint32* aDataAddress)
   229 	{
   230 	const TUint16* src=(const TUint16*)aDataAddress;
   231 	TUint8* dest=iBitmapBits;
   232 	for (TInt row=0;row<iSize.iHeight;++row)
   233 		{
   234 		for (TInt col=0;col<iSize.iWidth;++col)
   235 			{
   236 			dest[0]=TUint8((*src & 0x001f)<<3);
   237 			dest[0]=TUint8(dest[0]+(dest[0]>>5));
   238 			dest[1]=TUint8((*src & 0x07e0)>>3);
   239 			dest[1]=TUint8(dest[1]+(dest[1]>>6));
   240 			dest[2]=TUint8((*src & 0xf800)>>8);
   241 			dest[2]=TUint8(dest[2]+(dest[2]>>5));
   242 			++src;
   243 			dest+=3;
   244 			}
   245 		}
   246 	}
   247 
   248 void CDebugOsbWin::CopyU24Bpp(const TUint32* aDataAddress)
   249 	{
   250 	const TUint8* src=(const TUint8*)aDataAddress;
   251 	TUint8* dest=iBitmapBits;
   252 	for (TInt row=0;row<iSize.iHeight;++row)
   253 		{
   254 		for (TInt col=0;col<iSize.iWidth;++col)
   255 			{
   256 			dest[0]=*src++;
   257 			dest[1]=*src++;
   258 			dest[2]=*src++;
   259 			++src; // unpack, takes 4 bytes per pixel
   260 			dest+=3;
   261 			}
   262 		}
   263 	}
   264 
   265 void CDebugOsbWin::Copy24Bpp(const TUint32* aDataAddress)
   266 	{
   267 	const TUint8* src = (const TUint8*)aDataAddress;
   268 	Mem::Copy(iBitmapBits, src, 3 * iSize.iWidth * iSize.iHeight);
   269 	}
   270 
   271 HBITMAP* GetBitmap(HWND aHwnd)
   272 	{
   273 	TInt i;
   274 	for (i=0;i<CDebugOsbWin::iId;++i)
   275 		{
   276 		if (*(TheWindow[i])==aHwnd)
   277 			return TheBitmap[i];
   278 		}
   279 	return NULL;
   280 	}
   281 
   282 TInt32 APIENTRY WindowProc(HWND aHwnd,TUint aMsg,TUint aWparam,TInt32 aLparam)
   283 	{
   284 	switch (aMsg)
   285 		{
   286 		case WM_PAINT:
   287 			{
   288 			HBITMAP* hBitmap=GetBitmap(aHwnd);
   289 			if (hBitmap)
   290 				{
   291 				PAINTSTRUCT p;
   292 				BeginPaint(aHwnd,&p);
   293 		   		HDC hdcBits;
   294 				BITMAP bm;
   295 	    		hdcBits=CreateCompatibleDC(p.hdc);
   296 				GetObject(*hBitmap,sizeof(BITMAP),&bm);
   297 	    		SelectObject(hdcBits,*hBitmap);
   298 				RECT windowRect;
   299 				GetClientRect(aHwnd,&windowRect);
   300 				BitBlt(p.hdc,0,0,windowRect.right-windowRect.left,windowRect.bottom-windowRect.top,hdcBits,0,0,SRCCOPY);
   301 				DeleteDC(hdcBits);
   302 	 			EndPaint(aHwnd,&p);
   303 				}
   304 			}
   305 			return 0;
   306 		case WMA_RESIZE:
   307 			{
   308 			RECT rc;
   309 			GetWindowRect(aHwnd, &rc);
   310 			MoveWindow(aHwnd, rc.left, rc.top, aWparam, aLparam, TRUE);
   311 			}
   312 			break;
   313 		default:
   314 			return DefWindowProc(aHwnd,aMsg,aWparam,aLparam);
   315 		}
   316 	return 1;
   317 	}
   318 
   319 TInt CDebugOsbWin::ThreadMain(TAny* aArg)
   320     {
   321     CDebugOsbWin* self=(CDebugOsbWin*)aArg;
   322     if (!self || !self->iWin32)
   323     	return KErrArgument;
   324     TWin32Info* win32=self->iWin32;
   325     TSize size=self->iSize;
   326     WNDCLASS wndclass;
   327     const TText *szAppName=self->iName.Ptr();
   328     wndclass.style=CS_HREDRAW|CS_VREDRAW;
   329     wndclass.lpfnWndProc=WindowProc;
   330     wndclass.cbClsExtra=0;
   331     wndclass.cbWndExtra=0;
   332     wndclass.hInstance=NULL;
   333     wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
   334     wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
   335     wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
   336     wndclass.lpszMenuName=NULL;
   337     wndclass.lpszClassName=(LPCTSTR)szAppName;
   338 	self->iHExtra = GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
   339 	self->iVExtra = GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
   340     RegisterClass(&wndclass);
   341 	win32->iHwnd=CreateWindow((LPCTSTR)szAppName,
   342                     (LPCTSTR)szAppName,
   343                     WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
   344                     CW_USEDEFAULT,
   345                     (CDebugOsbWin::iId-1)*(size.iHeight+30),
   346                     size.iWidth+self->iHExtra,
   347                     size.iHeight+self->iVExtra,
   348                     NULL,
   349                     NULL,
   350                     NULL,
   351                     NULL);
   352     ShowWindow(win32->iHwnd, SW_SHOWNORMAL);
   353     UpdateWindow(win32->iHwnd);
   354 	// Now ConstructL can continue with ready to use HWND
   355 	self->iSem.Signal();
   356 	MSG msg;
   357 	// Can't use normal win32 loop. Theoritically, GetMessage with specific HWND param should do, but
   358 	// somehow it's still messing emulator main message loop.
   359 	// The standard win32 loop in debug log to window (deblogwn.cpp) doesn't  seem to work on 9.1
   360 	while (1)
   361 		{
   362 		if (PeekMessage(&msg,win32->iHwnd,0,0,PM_REMOVE))
   363 			DispatchMessage(&msg);
   364 		User::After(300*1000);
   365 		}
   366 	return KErrNone;
   367     }