sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: // Win32 dependent code for debugging wserv offscreenbuffer and UI surface on emulator sl@0: // sl@0: #include "osbwin.h" sl@0: #include "_windows.h" sl@0: sl@0: TInt CDebugOsbWin::iId=0; sl@0: const TInt KMaxBuffer=32; sl@0: HBITMAP* TheBitmap[KMaxBuffer]; sl@0: HWND* TheWindow[KMaxBuffer]; sl@0: sl@0: // Application window specific messages sl@0: #define WMA_RESIZE (WM_APP + 0) sl@0: sl@0: struct TWin32Info sl@0: { sl@0: HWND iHwnd; sl@0: HDC iHdc; sl@0: HBITMAP iHbitmap; sl@0: BITMAPINFO* iBitmapInfo; sl@0: }; sl@0: sl@0: EXPORT_C CDebugOsbWin* CDebugOsbWin::NewL(const TDesC& aName, TSize aSize) sl@0: { sl@0: CDebugOsbWin* self = new(ELeave) CDebugOsbWin(aName, aSize); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CDebugOsbWin::CDebugOsbWin(const TDesC& aName, TSize aSize): sl@0: iThreadCreated(EFalse), iSize(aSize), iName(aName) sl@0: {} sl@0: sl@0: EXPORT_C CDebugOsbWin::~CDebugOsbWin() sl@0: { sl@0: iSem.Close(); sl@0: if (iThreadCreated) sl@0: { sl@0: iThread.Terminate(0); sl@0: iThread.Close(); sl@0: } sl@0: if (iWin32) sl@0: { sl@0: if (iWin32->iHbitmap) sl@0: DeleteObject(iWin32->iHbitmap); sl@0: if (iWin32->iBitmapInfo) sl@0: User::Free(iWin32->iBitmapInfo); sl@0: if (iWin32->iHwnd && iWin32->iHdc) sl@0: ReleaseDC(iWin32->iHwnd,iWin32->iHdc); sl@0: delete iWin32; sl@0: } sl@0: if (iPalette) sl@0: delete iPalette; sl@0: --CDebugOsbWin::iId; sl@0: } sl@0: sl@0: void CDebugOsbWin::ConstructL() sl@0: { sl@0: if (iId>=KMaxBuffer) sl@0: User::Leave(KErrNoMemory); sl@0: iPalette=CPalette::NewDefaultL(EColor256); sl@0: iWin32=new(ELeave) TWin32Info; sl@0: // store window handle and bitmap association to global table sl@0: TheWindow[iId]=&(iWin32->iHwnd); sl@0: TheBitmap[iId]=&(iWin32->iHbitmap); sl@0: sl@0: _LIT(KIdFormat, " (%d)"); sl@0: iName.AppendFormat(KIdFormat, iId); sl@0: sl@0: ++iId; sl@0: iSem.CreateLocal(0); sl@0: const TInt KHeapSize=0x4000; sl@0: User::LeaveIfError(iThread.Create(iName,CDebugOsbWin::ThreadMain,KDefaultStackSize,KHeapSize,KHeapSize,this)); sl@0: iThread.SetPriority(EPriorityMuchLess); sl@0: iThread.Resume(); sl@0: iThreadCreated=ETrue; sl@0: iSem.Wait(); sl@0: // iHwnd initialized by WinMain sl@0: iWin32->iHdc=GetDC(iWin32->iHwnd); sl@0: SetMapMode(iWin32->iHdc,MM_TEXT); sl@0: SetROP2(iWin32->iHdc,R2_COPYPEN); sl@0: TInt byteSize=iSize.iWidth*iSize.iHeight*3; sl@0: iWin32->iBitmapInfo=(BITMAPINFO*)User::Alloc(sizeof(BITMAPINFO)); sl@0: User::LeaveIfNull(iWin32->iBitmapInfo); sl@0: iWin32->iBitmapInfo->bmiHeader.biBitCount=24; sl@0: iWin32->iBitmapInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); sl@0: iWin32->iBitmapInfo->bmiHeader.biWidth=iSize.iWidth; sl@0: iWin32->iBitmapInfo->bmiHeader.biHeight=-iSize.iHeight;//top-down DIB sl@0: iWin32->iBitmapInfo->bmiHeader.biPlanes=1; sl@0: iWin32->iBitmapInfo->bmiHeader.biCompression=BI_RGB; sl@0: iWin32->iHbitmap=CreateDIBSection(iWin32->iHdc,iWin32->iBitmapInfo,DIB_RGB_COLORS,(TAny**)&iBitmapBits,NULL,0); sl@0: User::LeaveIfNull(iWin32->iHbitmap); sl@0: Mem::Fill(iBitmapBits,byteSize,0xff); sl@0: } sl@0: sl@0: EXPORT_C void CDebugOsbWin::Refresh(TSize aSize, TDisplayMode aDisplayMode, const TUint32* aDataAddress) sl@0: { sl@0: TBool hasResized = EFalse; sl@0: sl@0: // When screen is rotated, the size can change as width and height are swapped. sl@0: if (iSize != aSize) sl@0: { sl@0: iSize = aSize; sl@0: iWin32->iBitmapInfo->bmiHeader.biWidth = aSize.iWidth; sl@0: iWin32->iBitmapInfo->bmiHeader.biHeight = -aSize.iHeight; //top-down DIB sl@0: hasResized = ETrue; sl@0: } sl@0: sl@0: switch (aDisplayMode) sl@0: { sl@0: case EGray4: sl@0: Copy2Bpp(aDataAddress); sl@0: break; sl@0: case EColor256: sl@0: Copy8Bpp(aDataAddress); sl@0: break; sl@0: case EColor4K: sl@0: Copy12Bpp(aDataAddress); sl@0: break; sl@0: case EColor64K: sl@0: Copy16Bpp(aDataAddress); sl@0: break; sl@0: case EColor16M: sl@0: Copy24Bpp(aDataAddress); sl@0: break; sl@0: case EColor16MU: sl@0: case EColor16MA: sl@0: case EColor16MAP: // Should really have alpha divided out sl@0: CopyU24Bpp(aDataAddress); sl@0: break; sl@0: default: sl@0: return; sl@0: } sl@0: SetDIBitsToDevice(iWin32->iHdc,0,0,iSize.iWidth,iSize.iHeight,0,0,0,iSize.iHeight,iBitmapBits, sl@0: ((LPBITMAPINFO)iWin32->iBitmapInfo),DIB_RGB_COLORS); sl@0: if (hasResized) sl@0: { sl@0: // This will cause a redraw so no need to invalidate. sl@0: PostMessage(iWin32->iHwnd, WMA_RESIZE, iSize.iWidth + iHExtra, iSize.iHeight + iVExtra); sl@0: } sl@0: else sl@0: { sl@0: InvalidateRect(iWin32->iHwnd,NULL,FALSE); sl@0: } sl@0: } sl@0: sl@0: void CDebugOsbWin::Copy2Bpp(const TUint32* aDataAddress) sl@0: { sl@0: const TUint8 gray[]={0,85,170,255}; sl@0: sl@0: const TUint8* src=(const TUint8*)aDataAddress; sl@0: TUint8* dest=iBitmapBits; sl@0: const TInt width=iSize.iWidth>>2; sl@0: for (TInt row=0;row>2) & 0x03); sl@0: TUint8 p3=TUint8((p1>>4) & 0x03); sl@0: TUint8 p4=TUint8((p1>>6) & 0x03); sl@0: p1&=0x03; sl@0: dest[0]=dest[1]=dest[2]=gray[p1]; sl@0: dest[3]=dest[4]=dest[5]=gray[p2]; sl@0: dest[6]=dest[7]=dest[8]=gray[p3]; sl@0: dest[9]=dest[10]=dest[11]=gray[p4]; sl@0: dest+=12; // 1 byte source equals to 4 destination pixels sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CDebugOsbWin::Copy8Bpp(const TUint32* aDataAddress) sl@0: { sl@0: if (!iPalette) sl@0: return; sl@0: const TUint8* src=(const TUint8*)aDataAddress; sl@0: TUint8* dest=iBitmapBits; sl@0: for (TInt row=0;rowGetEntry(*src++)); sl@0: dest[0]=TUint8(rgb.Blue()); sl@0: dest[1]=TUint8(rgb.Green()); sl@0: dest[2]=TUint8(rgb.Red()); sl@0: dest+=3; sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CDebugOsbWin::Copy12Bpp(const TUint32* aDataAddress) sl@0: { sl@0: sl@0: const TUint16* src=(const TUint16*)aDataAddress; sl@0: TUint8* dest=iBitmapBits; sl@0: for (TInt row=0;row> 4; sl@0: dest[2]=TUint8((*src & 0xf00)>>4); sl@0: dest[2]|=dest[2] >> 4; sl@0: ++src; sl@0: dest+=3; sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CDebugOsbWin::Copy16Bpp(const TUint32* aDataAddress) sl@0: { sl@0: const TUint16* src=(const TUint16*)aDataAddress; sl@0: TUint8* dest=iBitmapBits; sl@0: for (TInt row=0;row>5)); sl@0: dest[1]=TUint8((*src & 0x07e0)>>3); sl@0: dest[1]=TUint8(dest[1]+(dest[1]>>6)); sl@0: dest[2]=TUint8((*src & 0xf800)>>8); sl@0: dest[2]=TUint8(dest[2]+(dest[2]>>5)); sl@0: ++src; sl@0: dest+=3; sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CDebugOsbWin::CopyU24Bpp(const TUint32* aDataAddress) sl@0: { sl@0: const TUint8* src=(const TUint8*)aDataAddress; sl@0: TUint8* dest=iBitmapBits; sl@0: for (TInt row=0;rowiWin32) sl@0: return KErrArgument; sl@0: TWin32Info* win32=self->iWin32; sl@0: TSize size=self->iSize; sl@0: WNDCLASS wndclass; sl@0: const TText *szAppName=self->iName.Ptr(); sl@0: wndclass.style=CS_HREDRAW|CS_VREDRAW; sl@0: wndclass.lpfnWndProc=WindowProc; sl@0: wndclass.cbClsExtra=0; sl@0: wndclass.cbWndExtra=0; sl@0: wndclass.hInstance=NULL; sl@0: wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION); sl@0: wndclass.hCursor=LoadCursor(NULL, IDC_ARROW); sl@0: wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); sl@0: wndclass.lpszMenuName=NULL; sl@0: wndclass.lpszClassName=(LPCTSTR)szAppName; sl@0: self->iHExtra = GetSystemMetrics(SM_CXFIXEDFRAME) * 2; sl@0: self->iVExtra = GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION); sl@0: RegisterClass(&wndclass); sl@0: win32->iHwnd=CreateWindow((LPCTSTR)szAppName, sl@0: (LPCTSTR)szAppName, sl@0: WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, sl@0: CW_USEDEFAULT, sl@0: (CDebugOsbWin::iId-1)*(size.iHeight+30), sl@0: size.iWidth+self->iHExtra, sl@0: size.iHeight+self->iVExtra, sl@0: NULL, sl@0: NULL, sl@0: NULL, sl@0: NULL); sl@0: ShowWindow(win32->iHwnd, SW_SHOWNORMAL); sl@0: UpdateWindow(win32->iHwnd); sl@0: // Now ConstructL can continue with ready to use HWND sl@0: self->iSem.Signal(); sl@0: MSG msg; sl@0: // Can't use normal win32 loop. Theoritically, GetMessage with specific HWND param should do, but sl@0: // somehow it's still messing emulator main message loop. sl@0: // The standard win32 loop in debug log to window (deblogwn.cpp) doesn't seem to work on 9.1 sl@0: while (1) sl@0: { sl@0: if (PeekMessage(&msg,win32->iHwnd,0,0,PM_REMOVE)) sl@0: DispatchMessage(&msg); sl@0: User::After(300*1000); sl@0: } sl@0: return KErrNone; sl@0: }