diff -r 414d4b727fd9 -r 89bd4cfee505 graphicstest/uibench/src/tfbsfontrasterizeperf.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicstest/uibench/src/tfbsfontrasterizeperf.cpp Fri Sep 17 17:00:49 2010 +0300 @@ -0,0 +1,713 @@ +// Copyright (c) 2010 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: +// tfbsfontrasterizeperf.cpp +// +// + +/** + @file + @test + @internalComponent - Internal test code +*/ + +#include +#include "tfbsfontrasterizeperf.h" + +const TPtrC CTFbsFontRasterizePerf::TCacheTestParam::KLangText[] = {_L("Latin"), _L("Chinese")}; + +_LIT(KLatinText, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+-=|:;,.> testName; + testName.Format(_L("%S_%S_%d_%d"), &aTestName, &aParam.KLangText[aParam.iLang], aParam.iGlyphBitmapType, aParam.iHeight); + + iProfiler->SetStoreResultInTimingOrder(EFalse); + + iProfiler->InitResults(); + for (TInt count = 0; count < KCount; count++) + { + err = aTs->InstallFile(KChineseFontFileName, fontFileId); + TEST(err == KErrNone); + + err = aTs->GetNearestFontToDesignHeightInPixels(font, fontSpec); + TEST(err == KErrNone); + + for (TInt i = 0; i < aParam.iFrom; i++) // fill cache using the characters before aText[from] + { + const CFont::TCharacterDataAvailability availability = + font->GetCharacterData(aParam.iText[i], metrics, bitmapBytes, bitmapSize); + TEST(availability == CFont::EAllCharacterData); + } + + for (TInt i = aParam.iFrom; i < aParam.iTo; i++) // using characters before aText[to] to avoid using glyphCache/sessionCache + { + iProfiler->StartTimer(); + const CFont::TCharacterDataAvailability availability = + font->GetCharacterData(aParam.iText[i], metrics, bitmapBytes, bitmapSize); + iProfiler->MarkResultSetL(); + TEST(availability == CFont::EAllCharacterData); // May fails due to no enough memory for large size character on emulator + } + + aTs->ReleaseFont(font); // Release font, cache will be released also. + aTs->RemoveFile(fontFileId); + } + iProfiler->ResultsAnalysis(testName, 0, 0, 0, KIters); + } + +void CTFbsFontRasterizePerf::TestItypeRasterizeL() + { + // + // create heap and glyph data + // + RHeap* heap = UserHeap::ChunkHeap(NULL,0x10000,0x10000); + if (NULL == heap) + { + _LIT(KLog,"Not enough memory to create heap for test"); + INFO_PRINTF1(KLog); + User::Leave(KErrNoMemory); + } + + TOpenFontGlyphData* openFontGlyphData = TOpenFontGlyphData::New(heap, 36 * 1024); + TEST(openFontGlyphData != NULL); + + TBuf<48> testName; + RBuf16 ChineseText; + ChineseText.Create(256 * 5); + ChineseText.Append(KChineseText1); + ChineseText.Append(KChineseText2); + ChineseText.Append(KChineseText3); + ChineseText.Append(KChineseText4); + ChineseText.Append(KChineseText5); + ChineseText.CleanupClosePushL(); + + TCacheTestParam cacheTestParams[] = + { + {KFontSizeInPixels[0], AntiAliased::KGlyphBitmapType, TCacheTestParam::ELatin, KLatinText, 0, 0}, + {KFontSizeInPixels[0], MonoChrome::KGlyphBitmapType, TCacheTestParam::ELatin, KLatinText, 0, 0}, + {KFontSizeInPixels[1], AntiAliased::KGlyphBitmapType, TCacheTestParam::ELatin, KLatinText, 0, 0}, + {KFontSizeInPixels[1], MonoChrome::KGlyphBitmapType, TCacheTestParam::ELatin, KLatinText, 0, 0}, + {KFontSizeInPixels[2], AntiAliased::KGlyphBitmapType, TCacheTestParam::ELatin, KLatinText, 0, 0}, + {KFontSizeInPixels[2], MonoChrome::KGlyphBitmapType, TCacheTestParam::ELatin, KLatinText, 0, 0}, + {KFontSizeInPixels[0], AntiAliased::KGlyphBitmapType, TCacheTestParam::EChinese, ChineseText, 0, 0}, + {KFontSizeInPixels[0], MonoChrome::KGlyphBitmapType, TCacheTestParam::EChinese, ChineseText, 0, 0}, + {KFontSizeInPixels[1], AntiAliased::KGlyphBitmapType, TCacheTestParam::EChinese, ChineseText, 0, 0}, + {KFontSizeInPixels[1], MonoChrome::KGlyphBitmapType, TCacheTestParam::EChinese, ChineseText, 0, 0}, + {KFontSizeInPixels[2], AntiAliased::KGlyphBitmapType, TCacheTestParam::EChinese, ChineseText, 0, 0}, + {KFontSizeInPixels[2], MonoChrome::KGlyphBitmapType, TCacheTestParam::EChinese, ChineseText, 0, 0} + }; + + const TInt KNum = sizeof(cacheTestParams) / sizeof(cacheTestParams[0]); + for (TInt i = 0; i < KNum; i++) + { + DoTestItypeRasterizeL(heap, cacheTestParams[i], openFontGlyphData); + } + + CleanupStack::PopAndDestroy(&ChineseText); + heap->Free(openFontGlyphData); + heap->Close(); + } + +void CTFbsFontRasterizePerf::DoTestItypeRasterizeL(RHeap* aHeap, const TCacheTestParam& aParam, TOpenFontGlyphData* aGlyphData) + { + const TInt KCount = 10; + const TInt KIters = aParam.iText.Length() * KCount; + CBitmapFont* font = NULL; + TFontSpec fontSpec(KChineseFontName, aParam.iHeight); + fontSpec.iFontStyle.SetBitmapType(aParam.iGlyphBitmapType); + TBuf<48> testName; + testName.Format(_L("TestItypeRasterizeL_%S_%d_%d"), &aParam.KLangText[aParam.iLang], aParam.iGlyphBitmapType, aParam.iHeight); + + // Perform the iterations to test + iProfiler->InitResults(); + for (TInt count = 0; count < KCount; count++) + { + // + // create CFontStore + // + CFontStore* fontStore = CFontStore::NewL(aHeap); + CleanupStack::PushL(fontStore); + + // + // Install the rasterizer. + // + COpenFontRasterizer* rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); + CleanupStack::PushL(rasterizer); + fontStore->InstallRasterizerL(rasterizer); + CleanupStack::Pop(rasterizer); + + // + // Add font files + // + TInt ret = KErrNone; + TUid id1 = TUid::Uid(0); + TRAP(ret, id1 = fontStore->AddFileL(KChineseFontFileName)); + TEST(ret==KErrNone); + + // + // Create font + TInt err = fontStore->GetNearestFontToDesignHeightInPixels((CFont*&)font, fontSpec); + TEST(err == KErrNone); + + // + // rasterize + // + for (TInt i = 0; i < aParam.iText.Length(); i++) + { + iProfiler->StartTimer(); + font->OpenFont()->RasterizeL(aParam.iText[i], aGlyphData); + iProfiler->MarkResultSetL(); + } + + // + // release resources + // + fontStore->ReleaseFont(font); + CleanupStack::PopAndDestroy(fontStore); + } + iProfiler->ResultsAnalysis(testName, 0, 0, 0, KIters); + REComSession::FinalClose(); //close the ecom session opened by COpenFontRasterizer::NewL() + } + +void CTFbsFontRasterizePerf::TestLoadFontsAtStartupL() + { + const TInt KCount = 100; + RHeap* heap = UserHeap::ChunkHeap(NULL,0x10000,0x10000); + if (NULL == heap) + { + _LIT(KLog,"Not enough memory to create heap for test"); + INFO_PRINTF1(KLog); + User::Leave(KErrNoMemory); + } + + // Perform the iterations to test + iProfiler->InitResults(); + for(TInt count=KCount; count>0; --count) + { + CFontStore* fontStore = CFontStore::NewL(heap); + CleanupStack::PushL(fontStore); + + // Install the rasterizer. + COpenFontRasterizer* rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); + CleanupStack::PushL(rasterizer); + fontStore->InstallRasterizerL(rasterizer); + CleanupStack::Pop(rasterizer); + + iProfiler->StartTimer(); + fontStore->LoadFontsAtStartupL(); + iProfiler->MarkResultSetL(); + + CleanupStack::PopAndDestroy(fontStore); + } + iProfiler->ResultsAnalysis(_L("TestLoadFontsAtStartupL"), 0, 0, 0, KCount); + + REComSession::FinalClose(); //close the ecom session opened by COpenFontRasterizer::NewL() + heap->Close(); + } + +void CTFbsFontRasterizePerf::FontGetCharacterDataMultiSessionL() + { + CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL); + CleanupStack::PushL(ts); + TInt fontFileId = 0; + TInt err = ts->InstallFile(KChineseFontFileName, fontFileId); + TEST(err == KErrNone); + + TInt PixelHeightInTwips = 0; + TMachineInfoV1Buf machineInfoBuffer; + User::LeaveIfError(UserHal::MachineInfo(machineInfoBuffer)); + const TSize twipSize = machineInfoBuffer().iPhysicalScreenSize; + const TSize pixelSize = machineInfoBuffer().iDisplaySizeInPixels; + if (twipSize.iHeight > 0 && pixelSize.iHeight > 0) + PixelHeightInTwips = twipSize.iHeight * 1000 / pixelSize.iHeight; + INFO_PRINTF2(_L("KPixelHeightInTwips = %d"),PixelHeightInTwips); + + TFontSpec fontSpec(KChineseFontName, 2); + fontSpec.iHeight = 200; + + fontSpec.iFontStyle.SetBitmapType(AntiAliased::KGlyphBitmapType); + INFO_PRINTF1(_L("FontHeight = 200 pixel; BitmapType = AntiAliased - FontGetCharacterDataMultiSession")); + DoFontGetCharacterDataMultiSessionL(fontSpec); + + fontSpec.iFontStyle.SetBitmapType(MonoChrome::KGlyphBitmapType); + INFO_PRINTF1(_L("FontHeight = 200 pixel; BitmapType = MonoChrome - FontGetCharacterDataMultiSession")); + DoFontGetCharacterDataMultiSessionL(fontSpec); + + + fontSpec.iHeight = 50; + + fontSpec.iFontStyle.SetBitmapType(AntiAliased::KGlyphBitmapType); + INFO_PRINTF1(_L("FontHeight = 50 pixel; BitmapType = AntiAliased - FontGetCharacterDataMultiSession")); + DoFontGetCharacterDataMultiSessionL(fontSpec); + + fontSpec.iFontStyle.SetBitmapType(MonoChrome::KGlyphBitmapType); + INFO_PRINTF1(_L("FontHeight = 50 pixel; BitmapType = MonoChrome - FontGetCharacterDataMultiSession")); + DoFontGetCharacterDataMultiSessionL(fontSpec); + + ts->RemoveFile(fontFileId); + CleanupStack::PopAndDestroy(ts); + } + + +void CTFbsFontRasterizePerf::DoFontGetCharacterDataMultiSessionL(TFontSpec& aFontSpec) + { + RArray fileNames; + CleanupClosePushL(fileNames); + fileNames.AppendL(TPtrC(KInputFileLatin1)); + fileNames.AppendL(TPtrC(KInputFileChinese1)); + + const TInt KNumOfThreads = 4; + + TMultiThreadPara paras[KNumOfThreads]; + Mem::FillZ(paras,sizeof(TMultiThreadPara) * KNumOfThreads); + + RThread workers[KNumOfThreads]; + TRequestStatus statusArray[KNumOfThreads]; + + // --- KNumOfThreads Render same input file. (Latin and Chinese) + for(TInt count=0; count < fileNames.Count(); count++) + { + for(TInt i = 0; i < KNumOfThreads; i++) + { + paras[i].iSpec = &aFontSpec; + paras[i].iFileName.Set(fileNames[count]); + User::LeaveIfError(workers[i].Create(KNullDesC,FontGetCharacterDataThread,0x10000,0x1000,0x10000,reinterpret_cast(¶s[i]))); + statusArray[i] = KRequestPending; + workers[i].Logon(statusArray[i]); + } + for(TInt i = 0; i < KNumOfThreads; i++) + { + workers[i].Resume(); + } + + TBool bFinished = EFalse; + do{ + User::WaitForAnyRequest(); + bFinished = ETrue; + for(TInt i = 0; i < KNumOfThreads; i++) + { + if(statusArray[i] == KRequestPending) + { + bFinished = EFalse; + } + else + { + workers[i].Close(); + } + } + }while(!bFinished); + for(TInt i = 0; i < KNumOfThreads; i++) + { + TBuf<128> NameBuf; + NameBuf.AppendFormat(_L("Font-GetCharacterData-MutiSession-%d"),i); + _LIT(KVariantMax,"Max"); + _LIT(KVariantMin,"Min"); + _LIT(KVariantMean,"Mean"); + iProfiler->SqlInsert(&NameBuf,&KVariantMax,&KMicroSeconds,paras[i].iTimeMax); + iProfiler->SqlInsert(&NameBuf,&KVariantMin,&KMicroSeconds,paras[i].iTimeMin); + iProfiler->SqlInsert(&NameBuf,&KVariantMean,&KMicroSeconds,paras[i].iMean); + INFO_PRINTF3(_L("File = %S,Iters = %d"),¶s[i].iFileName, paras[i].iIters); + } + } + + // KNumOfThreads Render different input file. + + Mem::FillZ(paras,sizeof(TMultiThreadPara) * KNumOfThreads); + fileNames.Reset(); + // Append num of the files in same script = KNumOfThreads + fileNames.AppendL(TPtrC(KInputFileLatin1)); + fileNames.AppendL(TPtrC(KInputFileLatin2)); + fileNames.AppendL(TPtrC(KInputFileLatin3)); + fileNames.AppendL(TPtrC(KInputFileLatin4)); + fileNames.AppendL(TPtrC(KInputFileChinese1)); + fileNames.AppendL(TPtrC(KInputFileChinese2)); + fileNames.AppendL(TPtrC(KInputFileChinese3)); + fileNames.AppendL(TPtrC(KInputFileChinese4)); + + for (TInt count = 0; count < 2; count++) + { + for (TInt i = 0; i < KNumOfThreads; i++) + { + paras[i].iSpec = &aFontSpec; + paras[i].iFileName.Set(fileNames[i + count * KNumOfThreads]); + User::LeaveIfError(workers[i].Create(KNullDesC, + FontGetCharacterDataThread, 0x10000, 0x1000, 0x10000, + reinterpret_cast (¶s[i]))); + statusArray[i] = KRequestPending; + workers[i].Logon(statusArray[i]); + } + for (TInt i = 0; i < KNumOfThreads; i++) + { + workers[i].Resume(); + } + + TBool bFinished = EFalse; + do + { + User::WaitForAnyRequest(); + bFinished = ETrue; + for (TInt i = 0; i < KNumOfThreads; i++) + { + if (statusArray[i] == KRequestPending) + { + bFinished = EFalse; + } + else + { + workers[i].Close(); + } + } + } + while (!bFinished); + for (TInt i = 0; i < KNumOfThreads; i++) + { + TBuf<128> NameBuf; + NameBuf.AppendFormat(_L("Font-GetCharacterData-MutiSession-%d"), i); + _LIT(KVariantMax,"Max"); + _LIT(KVariantMin,"Min"); + _LIT(KVariantMean,"Mean"); + iProfiler->SqlInsert(&NameBuf, &KVariantMax, &KMicroSeconds, + paras[i].iTimeMax); + iProfiler->SqlInsert(&NameBuf, &KVariantMin, &KMicroSeconds, + paras[i].iTimeMin); + iProfiler->SqlInsert(&NameBuf, &KVariantMean, &KMicroSeconds, + paras[i].iMean); + INFO_PRINTF3(_L("File = %S,Iters = %d"),¶s[i].iFileName, paras[i].iIters); + } + } + + CleanupStack::PopAndDestroy(); + } + +TInt CTFbsFontRasterizePerf::FontGetCharacterDataThread(TAny * aPtr) + { + // Create cleanup stack + __UHEAP_MARK; + CTrapCleanup* cleanup = CTrapCleanup::New(); + + // Create output console + TRAPD(createError, FontGetCharacterDataWorkerL((reinterpret_cast (aPtr)))); + if (createError) + { + delete cleanup; + return createError; + } + + delete cleanup; + __UHEAP_MARKEND; + return KErrNone; + } + +void CTFbsFontRasterizePerf::FontGetCharacterDataWorkerL(TMultiThreadPara *aPara) + { + User::LeaveIfError(RFbsSession::Connect()); + CFbsFont* font = NULL; + CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL); + CleanupStack::PushL(ts); + + TFontSpec spec = *aPara->iSpec; + + User::LeaveIfError(ts->GetNearestFontToDesignHeightInPixels((CFont*&) font, spec)); + + TUint32 start = 0; + TUint32 end = 0; + TInt freq = 0; + User::LeaveIfError((HAL::Get(HALData::EFastCounterFrequency, freq))); + if(freq == 0) + { + User::Leave(KErrDivideByZero); + } + + // Load text from file + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + RFile in; + User::LeaveIfError(in.Open(fs, aPara->iFileName, EFileShareReadersOnly | EFileStreamText)); + CleanupClosePushL(in); + + TFileText content; + content.Set(in); + + TBool isFirstChar = ETrue; + TInt64 diffsum = 0; + + TBuf<512> buf; + while(KErrNone == content.Read(buf)) + { + TOpenFontCharMetrics metrics; + const TUint8* bitmap; + TSize bitmapSize; + for (TInt i = 0; i < buf.Length(); i++) + { + CFont::TCharacterDataAvailability ret; + start = User::FastCounter(); + ret = font->GetCharacterData(buf[i], metrics, bitmap, bitmapSize); + end = User::FastCounter(); + ASSERT(ret = CFont::EAllCharacterData); + TInt64 diff = (1000000 * (TInt64) (end - start)) / (TInt64) freq; + if(diff == 0) + { + diff = 1; + } + diffsum += diff; + ASSERT(diffsum >= 0); + aPara->iIters++; + if (isFirstChar) + { + aPara->iTimeMax = aPara->iTimeMin = diff; + isFirstChar = EFalse; + } + else + { + if (diff > aPara->iTimeMax) + { + aPara->iTimeMax = diff; + } + if (diff < aPara->iTimeMin) + { + aPara->iTimeMin = diff; + } + } + } + } + + // Write back Iters + if(aPara->iIters != 0) + { + aPara->iMean = diffsum / aPara->iIters; + } + RDebug::Print(_L("diffsum=%Ld"),diffsum); + + ts->ReleaseFont(font); + CleanupStack::PopAndDestroy(3); + RFbsSession::Disconnect(); + }