Merge 1. Pull in cpp files in the performance enhanced Khronos RI OVG files which are newly added. I've ignored platform-specific cpp files for linux, macosx, and null operating systems because this local solution has its own platform glue (i.e. facility to target Bitmaps but no full windowing support). I've ignored sfEGLInterface.cpp because this is used as a bridge to go from EGL to Nokia's Platsim which offers an EGL service. That's not relevant to this implementation because this is ARM side code, not Intel side. I just left a comment to sfEGLInterface.cpp in case we need to pick up this later on. The current code compiles on winscw. Prior to this fix, the code works on winscw, and can launch the SVG tiger (tiger.exe). That takes about 20 seconds to render. I hope to always be able to show this icon on each commit, and the plan is for the render time to reduce with this series of submissions. On this commit, the tiger renders ok in 20 seconds.
// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
// Win32 dependent code for debugging wserv offscreenbuffer and UI surface on emulator
//
#include "osbwin.h"
#include "_windows.h"
TInt CDebugOsbWin::iId=0;
const TInt KMaxBuffer=32;
HBITMAP* TheBitmap[KMaxBuffer];
HWND* TheWindow[KMaxBuffer];
// Application window specific messages
#define WMA_RESIZE (WM_APP + 0)
struct TWin32Info
{
HWND iHwnd;
HDC iHdc;
HBITMAP iHbitmap;
BITMAPINFO* iBitmapInfo;
};
EXPORT_C CDebugOsbWin* CDebugOsbWin::NewL(const TDesC& aName, TSize aSize)
{
CDebugOsbWin* self = new(ELeave) CDebugOsbWin(aName, aSize);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
CDebugOsbWin::CDebugOsbWin(const TDesC& aName, TSize aSize):
iThreadCreated(EFalse), iSize(aSize), iName(aName)
{}
EXPORT_C CDebugOsbWin::~CDebugOsbWin()
{
iSem.Close();
if (iThreadCreated)
{
iThread.Terminate(0);
iThread.Close();
}
if (iWin32)
{
if (iWin32->iHbitmap)
DeleteObject(iWin32->iHbitmap);
if (iWin32->iBitmapInfo)
User::Free(iWin32->iBitmapInfo);
if (iWin32->iHwnd && iWin32->iHdc)
ReleaseDC(iWin32->iHwnd,iWin32->iHdc);
delete iWin32;
}
if (iPalette)
delete iPalette;
--CDebugOsbWin::iId;
}
void CDebugOsbWin::ConstructL()
{
if (iId>=KMaxBuffer)
User::Leave(KErrNoMemory);
iPalette=CPalette::NewDefaultL(EColor256);
iWin32=new(ELeave) TWin32Info;
// store window handle and bitmap association to global table
TheWindow[iId]=&(iWin32->iHwnd);
TheBitmap[iId]=&(iWin32->iHbitmap);
_LIT(KIdFormat, " (%d)");
iName.AppendFormat(KIdFormat, iId);
++iId;
iSem.CreateLocal(0);
const TInt KHeapSize=0x4000;
User::LeaveIfError(iThread.Create(iName,CDebugOsbWin::ThreadMain,KDefaultStackSize,KHeapSize,KHeapSize,this));
iThread.SetPriority(EPriorityMuchLess);
iThread.Resume();
iThreadCreated=ETrue;
iSem.Wait();
// iHwnd initialized by WinMain
iWin32->iHdc=GetDC(iWin32->iHwnd);
SetMapMode(iWin32->iHdc,MM_TEXT);
SetROP2(iWin32->iHdc,R2_COPYPEN);
TInt byteSize=iSize.iWidth*iSize.iHeight*3;
iWin32->iBitmapInfo=(BITMAPINFO*)User::Alloc(sizeof(BITMAPINFO));
User::LeaveIfNull(iWin32->iBitmapInfo);
iWin32->iBitmapInfo->bmiHeader.biBitCount=24;
iWin32->iBitmapInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
iWin32->iBitmapInfo->bmiHeader.biWidth=iSize.iWidth;
iWin32->iBitmapInfo->bmiHeader.biHeight=-iSize.iHeight;//top-down DIB
iWin32->iBitmapInfo->bmiHeader.biPlanes=1;
iWin32->iBitmapInfo->bmiHeader.biCompression=BI_RGB;
iWin32->iHbitmap=CreateDIBSection(iWin32->iHdc,iWin32->iBitmapInfo,DIB_RGB_COLORS,(TAny**)&iBitmapBits,NULL,0);
User::LeaveIfNull(iWin32->iHbitmap);
Mem::Fill(iBitmapBits,byteSize,0xff);
}
EXPORT_C void CDebugOsbWin::Refresh(TSize aSize, TDisplayMode aDisplayMode, const TUint32* aDataAddress)
{
TBool hasResized = EFalse;
// When screen is rotated, the size can change as width and height are swapped.
if (iSize != aSize)
{
iSize = aSize;
iWin32->iBitmapInfo->bmiHeader.biWidth = aSize.iWidth;
iWin32->iBitmapInfo->bmiHeader.biHeight = -aSize.iHeight; //top-down DIB
hasResized = ETrue;
}
switch (aDisplayMode)
{
case EGray4:
Copy2Bpp(aDataAddress);
break;
case EColor256:
Copy8Bpp(aDataAddress);
break;
case EColor4K:
Copy12Bpp(aDataAddress);
break;
case EColor64K:
Copy16Bpp(aDataAddress);
break;
case EColor16M:
Copy24Bpp(aDataAddress);
break;
case EColor16MU:
case EColor16MA:
case EColor16MAP: // Should really have alpha divided out
CopyU24Bpp(aDataAddress);
break;
default:
return;
}
SetDIBitsToDevice(iWin32->iHdc,0,0,iSize.iWidth,iSize.iHeight,0,0,0,iSize.iHeight,iBitmapBits,
((LPBITMAPINFO)iWin32->iBitmapInfo),DIB_RGB_COLORS);
if (hasResized)
{
// This will cause a redraw so no need to invalidate.
PostMessage(iWin32->iHwnd, WMA_RESIZE, iSize.iWidth + iHExtra, iSize.iHeight + iVExtra);
}
else
{
InvalidateRect(iWin32->iHwnd,NULL,FALSE);
}
}
void CDebugOsbWin::Copy2Bpp(const TUint32* aDataAddress)
{
const TUint8 gray[]={0,85,170,255};
const TUint8* src=(const TUint8*)aDataAddress;
TUint8* dest=iBitmapBits;
const TInt width=iSize.iWidth>>2;
for (TInt row=0;row<iSize.iHeight;++row)
{
for (TInt col=0;col<width;++col)
{
TUint8 p1=*src++;
TUint8 p2=TUint8((p1>>2) & 0x03);
TUint8 p3=TUint8((p1>>4) & 0x03);
TUint8 p4=TUint8((p1>>6) & 0x03);
p1&=0x03;
dest[0]=dest[1]=dest[2]=gray[p1];
dest[3]=dest[4]=dest[5]=gray[p2];
dest[6]=dest[7]=dest[8]=gray[p3];
dest[9]=dest[10]=dest[11]=gray[p4];
dest+=12; // 1 byte source equals to 4 destination pixels
}
}
}
void CDebugOsbWin::Copy8Bpp(const TUint32* aDataAddress)
{
if (!iPalette)
return;
const TUint8* src=(const TUint8*)aDataAddress;
TUint8* dest=iBitmapBits;
for (TInt row=0;row<iSize.iHeight;++row)
{
for (TInt col=0;col<iSize.iWidth;++col)
{
const TRgb rgb(iPalette->GetEntry(*src++));
dest[0]=TUint8(rgb.Blue());
dest[1]=TUint8(rgb.Green());
dest[2]=TUint8(rgb.Red());
dest+=3;
}
}
}
void CDebugOsbWin::Copy12Bpp(const TUint32* aDataAddress)
{
const TUint16* src=(const TUint16*)aDataAddress;
TUint8* dest=iBitmapBits;
for (TInt row=0;row<iSize.iHeight;++row)
{
for (TInt col=0;col<iSize.iWidth;++col)
{
dest[0]=TUint8((*src & 0x00f));
dest[0]|=dest[0] << 4;
dest[1]=TUint8((*src & 0x0f0));
dest[1]|=dest[1] >> 4;
dest[2]=TUint8((*src & 0xf00)>>4);
dest[2]|=dest[2] >> 4;
++src;
dest+=3;
}
}
}
void CDebugOsbWin::Copy16Bpp(const TUint32* aDataAddress)
{
const TUint16* src=(const TUint16*)aDataAddress;
TUint8* dest=iBitmapBits;
for (TInt row=0;row<iSize.iHeight;++row)
{
for (TInt col=0;col<iSize.iWidth;++col)
{
dest[0]=TUint8((*src & 0x001f)<<3);
dest[0]=TUint8(dest[0]+(dest[0]>>5));
dest[1]=TUint8((*src & 0x07e0)>>3);
dest[1]=TUint8(dest[1]+(dest[1]>>6));
dest[2]=TUint8((*src & 0xf800)>>8);
dest[2]=TUint8(dest[2]+(dest[2]>>5));
++src;
dest+=3;
}
}
}
void CDebugOsbWin::CopyU24Bpp(const TUint32* aDataAddress)
{
const TUint8* src=(const TUint8*)aDataAddress;
TUint8* dest=iBitmapBits;
for (TInt row=0;row<iSize.iHeight;++row)
{
for (TInt col=0;col<iSize.iWidth;++col)
{
dest[0]=*src++;
dest[1]=*src++;
dest[2]=*src++;
++src; // unpack, takes 4 bytes per pixel
dest+=3;
}
}
}
void CDebugOsbWin::Copy24Bpp(const TUint32* aDataAddress)
{
const TUint8* src = (const TUint8*)aDataAddress;
Mem::Copy(iBitmapBits, src, 3 * iSize.iWidth * iSize.iHeight);
}
HBITMAP* GetBitmap(HWND aHwnd)
{
TInt i;
for (i=0;i<CDebugOsbWin::iId;++i)
{
if (*(TheWindow[i])==aHwnd)
return TheBitmap[i];
}
return NULL;
}
TInt32 APIENTRY WindowProc(HWND aHwnd,TUint aMsg,TUint aWparam,TInt32 aLparam)
{
switch (aMsg)
{
case WM_PAINT:
{
HBITMAP* hBitmap=GetBitmap(aHwnd);
if (hBitmap)
{
PAINTSTRUCT p;
BeginPaint(aHwnd,&p);
HDC hdcBits;
BITMAP bm;
hdcBits=CreateCompatibleDC(p.hdc);
GetObject(*hBitmap,sizeof(BITMAP),&bm);
SelectObject(hdcBits,*hBitmap);
RECT windowRect;
GetClientRect(aHwnd,&windowRect);
BitBlt(p.hdc,0,0,windowRect.right-windowRect.left,windowRect.bottom-windowRect.top,hdcBits,0,0,SRCCOPY);
DeleteDC(hdcBits);
EndPaint(aHwnd,&p);
}
}
return 0;
case WMA_RESIZE:
{
RECT rc;
GetWindowRect(aHwnd, &rc);
MoveWindow(aHwnd, rc.left, rc.top, aWparam, aLparam, TRUE);
}
break;
default:
return DefWindowProc(aHwnd,aMsg,aWparam,aLparam);
}
return 1;
}
TInt CDebugOsbWin::ThreadMain(TAny* aArg)
{
CDebugOsbWin* self=(CDebugOsbWin*)aArg;
if (!self || !self->iWin32)
return KErrArgument;
TWin32Info* win32=self->iWin32;
TSize size=self->iSize;
WNDCLASS wndclass;
const TText *szAppName=self->iName.Ptr();
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WindowProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=NULL;
wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=(LPCTSTR)szAppName;
self->iHExtra = GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
self->iVExtra = GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
RegisterClass(&wndclass);
win32->iHwnd=CreateWindow((LPCTSTR)szAppName,
(LPCTSTR)szAppName,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
(CDebugOsbWin::iId-1)*(size.iHeight+30),
size.iWidth+self->iHExtra,
size.iHeight+self->iVExtra,
NULL,
NULL,
NULL,
NULL);
ShowWindow(win32->iHwnd, SW_SHOWNORMAL);
UpdateWindow(win32->iHwnd);
// Now ConstructL can continue with ready to use HWND
self->iSem.Signal();
MSG msg;
// Can't use normal win32 loop. Theoritically, GetMessage with specific HWND param should do, but
// somehow it's still messing emulator main message loop.
// The standard win32 loop in debug log to window (deblogwn.cpp) doesn't seem to work on 9.1
while (1)
{
if (PeekMessage(&msg,win32->iHwnd,0,0,PM_REMOVE))
DispatchMessage(&msg);
User::After(300*1000);
}
return KErrNone;
}