|
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 } |