First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 // Win32 dependent code for debugging wserv offscreenbuffer and UI surface on emulator
21 TInt CDebugOsbWin::iId=0;
22 const TInt KMaxBuffer=32;
23 HBITMAP* TheBitmap[KMaxBuffer];
24 HWND* TheWindow[KMaxBuffer];
26 // Application window specific messages
27 #define WMA_RESIZE (WM_APP + 0)
34 BITMAPINFO* iBitmapInfo;
37 EXPORT_C CDebugOsbWin* CDebugOsbWin::NewL(const TDesC& aName, TSize aSize)
39 CDebugOsbWin* self = new(ELeave) CDebugOsbWin(aName, aSize);
40 CleanupStack::PushL(self);
42 CleanupStack::Pop(self);
46 CDebugOsbWin::CDebugOsbWin(const TDesC& aName, TSize aSize):
47 iThreadCreated(EFalse), iSize(aSize), iName(aName)
50 EXPORT_C CDebugOsbWin::~CDebugOsbWin()
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);
73 void CDebugOsbWin::ConstructL()
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);
83 _LIT(KIdFormat, " (%d)");
84 iName.AppendFormat(KIdFormat, iId);
88 const TInt KHeapSize=0x4000;
89 User::LeaveIfError(iThread.Create(iName,CDebugOsbWin::ThreadMain,KDefaultStackSize,KHeapSize,KHeapSize,this));
90 iThread.SetPriority(EPriorityMuchLess);
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);
112 EXPORT_C void CDebugOsbWin::Refresh(TSize aSize, TDisplayMode aDisplayMode, const TUint32* aDataAddress)
114 TBool hasResized = EFalse;
116 // When screen is rotated, the size can change as width and height are swapped.
120 iWin32->iBitmapInfo->bmiHeader.biWidth = aSize.iWidth;
121 iWin32->iBitmapInfo->bmiHeader.biHeight = -aSize.iHeight; //top-down DIB
125 switch (aDisplayMode)
128 Copy2Bpp(aDataAddress);
131 Copy8Bpp(aDataAddress);
134 Copy12Bpp(aDataAddress);
137 Copy16Bpp(aDataAddress);
140 Copy24Bpp(aDataAddress);
144 case EColor16MAP: // Should really have alpha divided out
145 CopyU24Bpp(aDataAddress);
150 SetDIBitsToDevice(iWin32->iHdc,0,0,iSize.iWidth,iSize.iHeight,0,0,0,iSize.iHeight,iBitmapBits,
151 ((LPBITMAPINFO)iWin32->iBitmapInfo),DIB_RGB_COLORS);
154 // This will cause a redraw so no need to invalidate.
155 PostMessage(iWin32->iHwnd, WMA_RESIZE, iSize.iWidth + iHExtra, iSize.iHeight + iVExtra);
159 InvalidateRect(iWin32->iHwnd,NULL,FALSE);
163 void CDebugOsbWin::Copy2Bpp(const TUint32* aDataAddress)
165 const TUint8 gray[]={0,85,170,255};
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)
172 for (TInt col=0;col<width;++col)
175 TUint8 p2=TUint8((p1>>2) & 0x03);
176 TUint8 p3=TUint8((p1>>4) & 0x03);
177 TUint8 p4=TUint8((p1>>6) & 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
188 void CDebugOsbWin::Copy8Bpp(const TUint32* aDataAddress)
192 const TUint8* src=(const TUint8*)aDataAddress;
193 TUint8* dest=iBitmapBits;
194 for (TInt row=0;row<iSize.iHeight;++row)
196 for (TInt col=0;col<iSize.iWidth;++col)
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());
207 void CDebugOsbWin::Copy12Bpp(const TUint32* aDataAddress)
210 const TUint16* src=(const TUint16*)aDataAddress;
211 TUint8* dest=iBitmapBits;
212 for (TInt row=0;row<iSize.iHeight;++row)
214 for (TInt col=0;col<iSize.iWidth;++col)
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;
228 void CDebugOsbWin::Copy16Bpp(const TUint32* aDataAddress)
230 const TUint16* src=(const TUint16*)aDataAddress;
231 TUint8* dest=iBitmapBits;
232 for (TInt row=0;row<iSize.iHeight;++row)
234 for (TInt col=0;col<iSize.iWidth;++col)
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));
248 void CDebugOsbWin::CopyU24Bpp(const TUint32* aDataAddress)
250 const TUint8* src=(const TUint8*)aDataAddress;
251 TUint8* dest=iBitmapBits;
252 for (TInt row=0;row<iSize.iHeight;++row)
254 for (TInt col=0;col<iSize.iWidth;++col)
259 ++src; // unpack, takes 4 bytes per pixel
265 void CDebugOsbWin::Copy24Bpp(const TUint32* aDataAddress)
267 const TUint8* src = (const TUint8*)aDataAddress;
268 Mem::Copy(iBitmapBits, src, 3 * iSize.iWidth * iSize.iHeight);
271 HBITMAP* GetBitmap(HWND aHwnd)
274 for (i=0;i<CDebugOsbWin::iId;++i)
276 if (*(TheWindow[i])==aHwnd)
282 TInt32 APIENTRY WindowProc(HWND aHwnd,TUint aMsg,TUint aWparam,TInt32 aLparam)
288 HBITMAP* hBitmap=GetBitmap(aHwnd);
292 BeginPaint(aHwnd,&p);
295 hdcBits=CreateCompatibleDC(p.hdc);
296 GetObject(*hBitmap,sizeof(BITMAP),&bm);
297 SelectObject(hdcBits,*hBitmap);
299 GetClientRect(aHwnd,&windowRect);
300 BitBlt(p.hdc,0,0,windowRect.right-windowRect.left,windowRect.bottom-windowRect.top,hdcBits,0,0,SRCCOPY);
309 GetWindowRect(aHwnd, &rc);
310 MoveWindow(aHwnd, rc.left, rc.top, aWparam, aLparam, TRUE);
314 return DefWindowProc(aHwnd,aMsg,aWparam,aLparam);
319 TInt CDebugOsbWin::ThreadMain(TAny* aArg)
321 CDebugOsbWin* self=(CDebugOsbWin*)aArg;
322 if (!self || !self->iWin32)
324 TWin32Info* win32=self->iWin32;
325 TSize size=self->iSize;
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,
343 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
345 (CDebugOsbWin::iId-1)*(size.iHeight+30),
346 size.iWidth+self->iHExtra,
347 size.iHeight+self->iVExtra,
352 ShowWindow(win32->iHwnd, SW_SHOWNORMAL);
353 UpdateWindow(win32->iHwnd);
354 // Now ConstructL can continue with ready to use HWND
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
362 if (PeekMessage(&msg,win32->iHwnd,0,0,PM_REMOVE))
363 DispatchMessage(&msg);
364 User::After(300*1000);