Update contrib.
1 // Copyright (c) 2009-2010 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.
19 @internalComponent - Internal Symbian test code
22 #include <test/graphicsfontutils.h>
23 #include <graphics/fbsglyphdataiterator.h>
24 #include <graphics/fbsglyphmetricsarray.h>
25 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
26 #include <sgresource/sgimage.h>
28 #include <vg/openvg.h>
29 typedef EGLBoolean (*TvgCreateEGLImageTargetKHRTypefPtr) (VGeglImageKHR image);
31 #include "tfbsglyphdata.h"
33 // Size of EGLSurface used for rendering to, in pixels.
34 const TSize KEglTargetSize(512, 512);
36 CTFbsGlyphData::CTFbsGlyphData()
38 SetTestStepName(KTFbsGlyphData);
41 CTFbsGlyphData::~CTFbsGlyphData()
45 TVerdict CTFbsGlyphData::doTestStepPreambleL()
47 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
48 User::LeaveIfError(iFbs.Connect());
49 User::LeaveIfError(iSgDriver.Open());
51 iCharCodeConverter = CCharCodeConverter::NewL();
52 return CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
55 TVerdict CTFbsGlyphData::doTestStepPostambleL()
57 delete iCharCodeConverter;
58 iCharCodeConverter = NULL;
59 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
63 return CTe_graphicsperformanceSuiteStepBase::doTestStepPostambleL();
66 TVerdict CTFbsGlyphData::doTestStepL()
68 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
69 INFO_PRINTF1(_L("CTFbsGlyphData can only be run with SgImage 'Lite'"));
70 return TestStepResult();
72 SetTestStepID(_L("GRAPHICS-UI-BENCH-0178"));
73 GlyphMetricsArrayL(ETestLanguageLatin, ETrue, 1000);
76 SetTestStepID(_L("GRAPHICS-UI-BENCH-0179"));
77 GlyphMetricsArrayL(ETestLanguageLatin, EFalse, 50000);
80 // Tests 180 and 181 require a CMap table in order to convert CharacterCodes to GlyphCodes.
81 SetTestStepID(_L("GRAPHICS-UI-BENCH-0180"));
82 GlyphMetricsArrayL(ETestLanguageHindi, ETrue, 25);
85 SetTestStepID(_L("GRAPHICS-UI-BENCH-0181"));
86 GlyphMetricsArrayL(ETestLanguageHindi, EFalse, 50000);
89 SetTestStepID(_L("GRAPHICS-UI-BENCH-0182"));
90 GlyphMetricsQuerySingleGlyphL();
93 SetTestStepID(_L("GRAPHICS-UI-BENCH-0183"));
94 GlyphDataIteratorOpenL(ETestLanguageLatin, ETrue, 50);
97 SetTestStepID(_L("GRAPHICS-UI-BENCH-0184"));
98 GlyphDataIteratorOpenL(ETestLanguageLatin, EFalse, 500);
101 // Tests 185 and 186 require a CMap table in order to convert CharacterCodes to GlyphCodes.
102 SetTestStepID(_L("GRAPHICS-UI-BENCH-0185"));
103 GlyphDataIteratorOpenL(ETestLanguageHindi, ETrue, 10);
106 SetTestStepID(_L("GRAPHICS-UI-BENCH-0186"));
107 GlyphDataIteratorOpenL(ETestLanguageHindi, EFalse, 5000);
110 SetTestStepID(_L("GRAPHICS-UI-BENCH-0187"));
111 GlyphDataIteratorOpenSingleFontL();
114 SetTestStepID(_L("GRAPHICS-UI-BENCH-0188"));
115 GlyphMetricsQueryUnrasterizedL();
118 SetTestStepID(_L("GRAPHICS-UI-BENCH-0189"));
119 GlyphMetricsQueryPreRasterizedL();
122 SetTestStepID(_L("GRAPHICS-UI-BENCH-0190"));
126 return TestStepResult();
130 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
132 @SYMTestCaseID GRAPHICS-UI-BENCH-0178...0181
139 Measures the performance of calling RFbsGlyphMetricsArray::Get() with different sample data.
140 The sample data can be a single word, or a very long array of glyphs, in latin or non-latin
141 alphabets. At each repetition a different font is used, cycled over nine fonts, to reduce the
142 effect of having cached glyphs.
145 i. Create some sample fonts to cycle through.
146 ii. Load sample data from config file, specified by aSampleDataKey.
147 iii. Create RFbsGlyphMetricsArray, open on sample data.
148 iv. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting font at each repetition.
149 v. Measure time from from first to last repetition.
151 @param aLanguage The language this test will use.
152 @param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
153 will make the test use the short string data.
154 @param aReps The number of times to repeat the test.
156 void CTFbsGlyphData::GlyphMetricsArrayL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
159 TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
160 KTestName.Format(_L("GlyphMetricsArray %S"), &KTestVariant);
162 // Create some test fonts using the font factory.
163 CTFontFactory* fontFactory = CTFontFactory::NewLC();
164 fontFactory->CreateFontsL(aLanguage, 9);
166 // Load the sample string data from the config file.
167 TInt numGlyphCodes = 0;
169 LoadConfigSampleDataL(fontFactory->NextFont(), aLanguage, aLongData, glyphCodes, numGlyphCodes);
173 RFbsGlyphMetricsArray array;
174 CleanupClosePushL(array);
175 iProfiler->InitResults();
176 for (TInt rep = aReps; (rep != 0) && (err == KErrNone); --rep)
178 err = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
180 iProfiler->MarkResultSetL();
181 TESTE(err == KErrNone, err);
182 iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
184 CleanupStack::PopAndDestroy(2); // array, fontFactory
185 delete [] glyphCodes;
189 @SYMTestCaseID GRAPHICS-UI-BENCH-0182
196 Measures the performance of calling RFbsGlyphDataIterator::Get() with a single glyph,
197 versus CFont::GetCharacterData(). Using a single glyph code is a very common use case.
198 The glyph and the font is changed at each iteration.
201 i. Create some sample fonts to cycle through.
202 ii. Create RFbsGlyphMetricsArray.
203 iii. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting the glyph at
205 iv. Measure time from from first to last iteration.
206 v. Repeat steps iii. and iv. with CFont::GetCharacterData().
208 void CTFbsGlyphData::GlyphMetricsQuerySingleGlyphL()
210 _LIT(KTestName, "GlyphMetricsQuerySingleGlyph");
211 const TInt KNumIterations = 50000;
213 TBuf<128> KTestNameVariant;
215 // Create some test fonts using the font factory.
216 CTFontFactory* fontFactory = CTFontFactory::NewLC();
218 // Run the test for RFbsGlyphMetricsArray, with a different character
219 // and font for each iteration.
220 KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
221 fontFactory->CreateFontsL(ETestLanguageLatin, 9);
222 RFbsGlyphMetricsArray array;
223 CleanupClosePushL(array);
224 iProfiler->InitResults();
225 for (TInt rep = KNumIterations; rep != 0 && (err == KErrNone); --rep)
227 const TUint KGlyphCode = 32 + (rep % 96);
228 err = array.Get(*(fontFactory->NextFont()), &KGlyphCode, 1);
230 iProfiler->MarkResultSetL();
231 TESTE(err == KErrNone, err);
232 CleanupStack::PopAndDestroy(1); // array
233 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
234 fontFactory->ReleaseFonts();
236 // Run the test for GetCharacterData(), with a different character
237 // and font for each iteration.
238 KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
239 fontFactory->CreateFontsL(ETestLanguageLatin, 9);
240 TOpenFontCharMetrics metrics;
241 const TUint8* bitmapData = NULL;
243 iProfiler->InitResults();
244 for (TInt rep = KNumIterations; rep != 0; --rep)
246 const TUint KGlyphCode = 32 + (rep % 96);
247 fontFactory->NextFont()->GetCharacterData(KGlyphCode, metrics, bitmapData, bitmapSize);
249 iProfiler->MarkResultSetL();
250 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
252 CleanupStack::PopAndDestroy(1); // fontFactory
256 @SYMTestCaseID GRAPHICS-UI-BENCH-0183...0186
263 Measures the performance of calling RFbsGlyphDataIterator::Open() with different
264 sample data, and iterating through the data with RFbsGlyphDataIterator::Next().
265 The sample data can be a single word, or a very long array of glyphs,
266 in various languages. At each repetition a different font is used, cycled
270 i. Create some sample fonts to cycle through.
271 ii. Create RFbsGlyphDataIterator.
272 iii. For each repetition, call RFbsGlyphDataIterator::Open(), adjusting the glyph at each
273 iteration. The font is changed at each repetition.
274 iv. Measure time from from first to last repetition.
276 @param aLanguage The language this test will use.
277 @param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
278 will make the test use the short string data.
279 @param aReps The number of times to repeat the test.
281 void CTFbsGlyphData::GlyphDataIteratorOpenL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
284 TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
285 KTestName.Format(_L("GlyphDataIteratorOpen %S"), &KTestVariant);
287 // Create some test fonts using the font factory.
288 CTFontFactory* fontFactory = CTFontFactory::NewLC();
289 fontFactory->CreateFontsL(aLanguage, 9);
291 // Load the sample string data from the config file.
292 TInt numGlyphCodes = 0;
294 LoadConfigSampleDataL(fontFactory->NextFont(), aLanguage, aLongData, glyphCodes, numGlyphCodes);
297 TInt err = KErrNotFound;
298 RFbsGlyphDataIterator iter;
299 CleanupClosePushL(iter);
300 iProfiler->InitResults();
301 for (TInt rep = aReps; (rep != 0) && (err == KErrNotFound); --rep)
303 err = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
304 for (; err == KErrNone; err = iter.Next())
310 iProfiler->MarkResultSetL();
311 TESTE(err == KErrNotFound, err);
313 CleanupStack::PopAndDestroy(2); // iter, fontFactory
314 iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
315 delete [] glyphCodes;
319 @SYMTestCaseID GRAPHICS-UI-BENCH-0187
326 Measures the performance of calling RFbsGlyphDataIterator::Open() with different
327 lengthed arrays but the same font. The sample data is a long array of characters.
330 i. Create a single test font
331 ii. Create RFbsGlyphDataIterator.
332 iii. Pass an array to RFbsGlyphDataIterator::Open(), starting with a single glyph.
333 For each iteration, increase the length of the array by one until the entire
334 string has been opened.
335 iv. Measure the time to perform all the iterations.
337 @param aSampleDataKey The string key to lookup under the GlyphArraySampleText section of the
338 config file where the sample data is read.
339 @param aReps The number of times to repeat the test.
341 void CTFbsGlyphData::GlyphDataIteratorOpenSingleFontL()
343 _LIT(KTestName, "GlyphDataIteratorOpenSingleFont");
344 // A cap on the max number of iterations to complete.
345 const TInt KMaxNumIterations = 200;
346 const TTestLanguage KTestLanguage = ETestLanguageHindi;
348 // Create some test fonts using the font factory.
349 CTFontFactory* fontFactory = CTFontFactory::NewLC();
350 fontFactory->CreateFontsL(KTestLanguage, 1);
351 CFbsFont* font = fontFactory->NextFont();
353 // Load the sample string data from the config file.
354 TInt numGlyphCodes = 0;
356 LoadConfigSampleDataL(font, KTestLanguage, ETrue, glyphCodes, numGlyphCodes);
358 const TInt KNumRepetitions = Min<TInt>(numGlyphCodes - 1, KMaxNumIterations);
359 RFbsGlyphDataIterator iter;
360 CleanupClosePushL(iter);
361 TInt iterErr = KErrNone;
363 iProfiler->InitResults();
364 for (glyphCount = 1; (glyphCount < KNumRepetitions); ++glyphCount)
366 iterErr = iter.Open(*font, glyphCodes, glyphCount);
367 for (; iterErr == KErrNone; iterErr = iter.Next())
373 iProfiler->MarkResultSetL();
374 TEST(glyphCount == KNumRepetitions);
375 TESTE(iterErr == KErrNotFound, iterErr);
377 const TInt KAvgNumCharsPerIteration = KNumRepetitions/2;
378 iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumRepetitions, KAvgNumCharsPerIteration);
380 CleanupStack::PopAndDestroy(2); // iter, fontFactory
381 delete [] glyphCodes;
384 @SYMTestCaseID GRAPHICS-UI-BENCH-0188
391 Measures the performance of querying the TOpenFontCharMetrics using the different
392 available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
393 are compared against each other, using the same fonts, and same sample data.
394 This test uses glyphs that have not been rasterized before, therefore for certain
395 APIs this will mean rasterizing the glyphs.
398 i. Load sample text data from config file.
399 ii. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
400 1. Create 50 new fonts.
401 2. Run the test, calling the necessary API once per font/loop.
402 3. For GetCharacterData() and RFbsGlyphDataIterator(), cycle through each glyph
403 to ensure all metrics have been retrieved. This is not necessary for
404 RFbsGlyphMetricsArray.
405 4. Measure time between first and last font/loop.
406 5. Destroy test fonts so that next test has to re-rasterize the glyphs.
408 @SYMTestExpectedResults
409 Since this test uses non-rasterized fonts, RFbsGlyphMetricsArray should be faster than
410 GetCharacterData() and RFbsGlyphDataIterator, which both rasterize the glyphs in order to
411 get their metrics information.
413 void CTFbsGlyphData::GlyphMetricsQueryUnrasterizedL()
415 _LIT(KTestName, "GlyphMetricsQueryUnrasterized");
417 TBuf<128> KTestNameVariant;
418 // First do the test for the iterator. To ensure fair comparison with
419 // RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
420 // for each glyph is found.
421 KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
423 const TInt KNumFonts = 50;
424 const TTestLanguage KTestLanguage = ETestLanguageLatin;
426 // Create some test fonts using the font factory.
427 CTFontFactory* fontFactory = CTFontFactory::NewLC();
428 fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
430 // Load the sample string data from the config file. Both the iterator and the
431 // array will use this same sample data.
432 TInt numGlyphCodes = 0;
434 LoadConfigSampleDataL(fontFactory->NextFont(), KTestLanguage, ETrue, glyphCodes, numGlyphCodes);
436 RFbsGlyphDataIterator iter;
437 CleanupClosePushL(iter);
438 TInt iterErr = KErrNone;
440 iProfiler->InitResults();
441 for (rep = KNumFonts; (rep != 0); --rep)
443 iterErr = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
444 for (; iterErr == KErrNone; iterErr = iter.Next())
450 iProfiler->MarkResultSetL();
452 TESTE(iterErr == KErrNotFound, iterErr);
453 CleanupStack::PopAndDestroy(1); // iter
454 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
456 // Second, do the test for the array. This should be faster.
457 // Destroy the fonts and re-create them so that they have to be re-rasterized
458 // for a fair comparison.
459 TInt arrayErr = KErrNone;
460 KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
461 fontFactory->ReleaseFonts();
462 fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
463 RFbsGlyphMetricsArray array;
464 CleanupClosePushL(array);
465 iProfiler->InitResults();
466 for (TInt rep = KNumFonts; (rep != 0) && (arrayErr == KErrNone); --rep)
468 arrayErr = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
470 iProfiler->MarkResultSetL();
471 CleanupStack::PopAndDestroy(1); // array
473 TESTE(arrayErr == KErrNone, arrayErr);
474 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
476 // Third, do the test using GetCharacterData() to get the metrics.
477 // Destroy the fonts and re-create them so that they have to be re-rasterized
478 // for a fair comparison.
479 KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
480 fontFactory->ReleaseFonts();
481 fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
482 iProfiler->InitResults();
483 const TUint8* bitmapData = NULL;
485 TOpenFontCharMetrics metrics;
486 for (TInt rep = KNumFonts; (rep != 0); --rep)
488 CFbsFont* font = fontFactory->NextFont();
489 for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
491 font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
494 iProfiler->MarkResultSetL();
495 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
497 CleanupStack::PopAndDestroy(1); // fontFactory
498 delete [] glyphCodes;
502 @SYMTestCaseID GRAPHICS-UI-BENCH-0189
509 Measures the performance of querying the TOpenFontCharMetrics using the different
510 available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
511 are compared against each other, using the same fonts, and same sample data.
512 This test uses glyphs that have already been rasterized, thereby possibly reducing the
513 extra overhead this has.
516 i. Load sample text data from config file.
517 ii. Create test font.
518 iii. Pre-rasterize glyphs using RFbsGlyphDataIterator. This will rasterize the glyphs
519 and cause them to be cached for use by all the APIs tested here.
520 iv. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
521 1. Begin the loop, calling the necessary API once per font/loop.
522 2. For each glyph, request the glyph metrics.
523 3. Measure time between first and last font/loop.
524 v. Destroy test font.
526 @SYMTestExpectedResults
527 All results should be improved over GlyphMetricsQueryUnrasterized (GRAPHICS-UI-BENCH-0187).
528 since no rasterizing should take place during these tests.
530 void CTFbsGlyphData::GlyphMetricsQueryPreRasterizedL()
532 _LIT(KTestName, "GlyphMetricsQueryPreRasterized");
533 TBuf<128> KTestNameVariant;
534 const TInt KNumIterations = 500;
535 const TTestLanguage KTestLanguage = ETestLanguageLatin;
537 // Create a test font using the font factory.
538 CTFontFactory* fontFactory = CTFontFactory::NewLC();
539 fontFactory->CreateFontsL(ETestLanguageLatin, 1);
540 CFbsFont* font = fontFactory->NextFont();
542 TInt numGlyphCodes = 0;
544 LoadConfigSampleDataL(font, KTestLanguage, ETrue, glyphCodes, numGlyphCodes);
546 TInt iterErr = KErrNone;
548 // Rasterize the glyphs first.
549 RFbsGlyphDataIterator iter;
550 CleanupClosePushL(iter);
551 for (rep = KNumIterations; (rep != 0) ; --rep)
553 iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
554 for (; iterErr == KErrNone; iterErr = iter.Next())
561 TESTE(iterErr == KErrNotFound, iterErr);
563 TOpenFontCharMetrics metrics;
565 // First do the test for the iterator. To ensure fair comparison with
566 // RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
567 // for each glyph is found.
569 KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
570 iProfiler->InitResults();
571 for (TInt rep = KNumIterations; (rep != 0); --rep)
573 for (iterErr = iter.Open(*font, glyphCodes, numGlyphCodes); iterErr == KErrNone; iterErr = iter.Next())
575 metrics = iter.Metrics();
579 iProfiler->MarkResultSetL();
580 TESTE(iterErr == KErrNotFound, iterErr);
581 CleanupStack::PopAndDestroy(1); // iter
582 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
585 // Second, do the test for the array. This should be faster.
586 TInt arrayErr = KErrNone;
587 KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
588 RFbsGlyphMetricsArray array;
589 CleanupClosePushL(array);
590 iProfiler->InitResults();
591 for (TInt rep = KNumIterations; (rep != 0) && (arrayErr == KErrNone); --rep)
593 arrayErr = array.Get(*font, glyphCodes, numGlyphCodes);
594 for (TInt i = 0; i < numGlyphCodes; ++i)
599 iProfiler->MarkResultSetL();
600 TESTE(arrayErr == KErrNone, arrayErr);
601 CleanupStack::PopAndDestroy(1); // array
602 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
605 // Third, do the test using GetCharacterData() to get the metrics.
606 KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
607 const TUint8* bitmapData;
610 iProfiler->InitResults();
611 for (TInt rep = KNumIterations; (rep != 0); --rep)
613 for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
615 font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
618 iProfiler->MarkResultSetL();
619 iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
621 CleanupStack::PopAndDestroy(1); // fontFactory
622 delete [] glyphCodes;
626 @SYMTestCaseID GRAPHICS-UI-BENCH-0190
633 Measures the end-to-end performance of using Khronos APIs to render glyphs using the
634 RFbsGlyphDataIterator API. Positioning is very basic and is not reflective of a production-
635 quality text-rendering algorithm, but serves as a useful benchmark of the overall
636 text-rendering performance using this API.
639 i. Create a sample font to use.
640 ii. Create a RSgImage to be used as a target for Khronos API rendering.
641 iii. Set-up EGL and OpenVG.
642 iv. Construct RFbsGlyphDataIterator, and open on sample data. At each iteration:
643 1. Create an EGLImage from the RSgImage.
644 2. Create a VGImage from the EGLImage.
645 3. Render the VGImage using vgDrawImage().
648 6. Advance the current rendering position for the next glyph, ensuring that every glyph
649 will be within the bounds of the target surface.
650 v. Measure time from from first to last iteration.
652 void CTFbsGlyphData::GlyphRenderingL()
654 _LIT(KTestName, "GlyphRendering");
655 const TInt KNumIterations = 500;
656 const TTestLanguage KTestLanguage = ETestLanguageHindi;
658 // Create some test fonts using the font factory.
659 CTFontFactory* fontFactory = CTFontFactory::NewLC();
660 fontFactory->CreateFontsL(KTestLanguage, 1, 20);
661 CFbsFont* font = fontFactory->NextFont();
662 const TInt KFontHeightInPixels = font->HeightInPixels();
664 // Create RSgImage to be used as OpenVG Pixmap Surface
667 TInt err = target.Create(TSgImageInfo(KEglTargetSize, ESgPixelFormatARGB_8888_PRE, ESgUsageBitOpenVgSurface));
668 TESTL(err == KErrNone);
669 CleanupClosePushL(target);
671 // Initialize EGL/OpenVG for rendering.
672 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
673 if (display == EGL_NO_DISPLAY)
675 ERR_PRINTF2(_L("Failed to get EGLDisplay. [eglError=%X]"), eglGetError());
676 User::Leave(KErrGeneral);
678 TESTL(display != EGL_NO_DISPLAY);
679 if (EGL_FALSE == eglInitialize(display, NULL, NULL))
681 ERR_PRINTF2(_L("Failed to initialize EGLDisplay. [eglError=%X]"), eglGetError());
682 User::Leave(KErrGeneral);
684 eglBindAPI(EGL_OPENVG_API);
686 EGLint imageAttribs[] =
688 EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE,
691 EGLint configAttribs[] =
693 EGL_MATCH_NATIVE_PIXMAP, (EGLint)&target,
694 EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
695 EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
699 const EGLint KPixmapAttribsVgAlphaFormatPre[] =
701 EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE,
706 EGLint numConfigs = 0;
707 if (EGL_FALSE == eglChooseConfig(display, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
709 ERR_PRINTF3(_L("Failed to find suitable EGLConfig. [eglError=%X, configs=%d]"), eglGetError(), numConfigs);
710 User::Leave(KErrGeneral);
712 EGLContext context = eglCreateContext(display, configId, EGL_NO_CONTEXT, NULL);
713 if (context == EGL_NO_CONTEXT)
715 ERR_PRINTF2(_L("Failed to create EGLContext. [eglError=%X]"), eglGetError());
716 User::Leave(KErrGeneral);
718 EGLSurface surface = eglCreatePixmapSurface(display, configId, &target, KPixmapAttribsVgAlphaFormatPre);
719 if (EGL_FALSE == eglMakeCurrent(display, surface, surface, context))
721 ERR_PRINTF2(_L("Failed to create make surface and context current. [eglError=%X]"), eglGetError());
722 eglDestroyContext(display, context);
723 User::Leave(KErrGeneral);
726 // Load the necessary EGL extensions...
727 TvgCreateEGLImageTargetKHRTypefPtr vgCreateImageTargetKHR;
728 PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
729 PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
730 eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
731 eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
732 vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
733 if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
735 ERR_PRINTF1(_L("Failed to get EGL Image extension functions."));
736 User::Leave(KErrNotSupported);
738 // Now we have an OpenVG window to render to!
740 TInt numGlyphCodes = 0;
742 LoadConfigSampleDataL(font, KTestLanguage, EFalse, glyphCodes, numGlyphCodes);
744 // Set up an identity matrix compatible with the Symbian co-ordinate system.
745 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
747 vgTranslate(0, -KFontHeightInPixels);
748 VGfloat vgIdentityMatrix[16];
749 vgGetMatrix(vgIdentityMatrix);
751 RFbsGlyphDataIterator iter;
752 CleanupClosePushL(iter);
754 // Render some glyphs.
755 TInt iterErr = KErrNone;
757 vgClear(0, 0, KEglTargetSize.iWidth, KEglTargetSize.iHeight);
758 TPoint glyphOrigin(0, 0);
759 iProfiler->InitResults();
760 for (rep = 0; rep < KNumIterations; rep++)
762 iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
763 for (;iterErr == KErrNone; iterErr = iter.Next())
765 const TOpenFontCharMetrics& metrics = iter.Metrics();
766 const RSgImage& glyphSgImage = iter.Image();
767 EGLImageKHR eglImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
768 reinterpret_cast<EGLClientBuffer>(&glyphSgImage), imageAttribs);
769 VGImage vgImage = vgCreateImageTargetKHR(eglImage);
771 // wrapped text placement.
772 TInt horizAdvance = metrics.HorizAdvance();
773 if (glyphOrigin.iX + horizAdvance >= KEglTargetSize.iWidth)
775 vgLoadMatrix(vgIdentityMatrix);
777 glyphOrigin.iY -= KFontHeightInPixels;
778 if (glyphOrigin.iY - KFontHeightInPixels < -KEglTargetSize.iHeight)
782 vgTranslate(glyphOrigin.iX, glyphOrigin.iY);
785 vgDrawImage(vgImage);
786 vgDestroyImage(vgImage);
787 eglDestroyImageKHR(display, eglImage);
789 // Move to next glyph position.
790 glyphOrigin.iX += horizAdvance;
791 vgTranslate(horizAdvance, 0);
794 eglSwapBuffers(display, surface);
796 iProfiler->MarkResultSetL();
797 iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumIterations, numGlyphCodes);
798 TEST(rep == KNumIterations);
799 TESTE(iterErr == KErrNotFound, iterErr);
800 WriteTargetOutput(KTestName());
802 eglDestroySurface(display, surface);
803 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
804 eglTerminate(display);
807 CleanupStack::PopAndDestroy(3); // iter, target, fontFactory
808 delete [] glyphCodes;
813 Captures the EGL Surface (it is assumed to be an OpenVG surface) to a 256-grey CFbsBitmap,
814 used when sanity-checking bitmaps are enabled.
816 CFbsBitmap* CTFbsGlyphData::GetTargetAsBitmapL()
818 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
819 // For debugging purposes only.
820 // Capture the final state of the EGL Pixmap surface as an mbm.
821 const TInt KDataStride = KEglTargetSize.iWidth;
823 TUint8* imageScanline = reinterpret_cast<TUint8*>(User::AllocZL(KDataStride));
824 CleanupStack::PushL(imageScanline);
825 CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
826 CleanupStack::PushL(bitmap);
827 User::LeaveIfError(bitmap->Create(KEglTargetSize, EGray256));
828 bitmap->BeginDataAccess();
829 TUint8* dataAddress = reinterpret_cast<TUint8*>(bitmap->DataAddress());
830 const TInt dataStride = bitmap->DataStride();
831 for (TInt scanline = 0; scanline < KEglTargetSize.iHeight; scanline++)
833 vgReadPixels(imageScanline, KDataStride, VG_A_8, 0, scanline, KEglTargetSize.iWidth, 1);
834 Mem::Copy(dataAddress, imageScanline, KEglTargetSize.iWidth);
835 dataAddress += dataStride;
837 bitmap->EndDataAccess(EFalse);
838 CleanupStack::Pop(2); // bitmap, imageScanline
846 Utility method. Loads sample glyph code data from the config ini file
848 @param aFont The font that the glyph codes will be associated with.
849 @param aLanguage The language variant to load from the config file as sample data.
850 @param aLongData Whether to use the long variant (ETrue) or short variant (EFalse)
851 of the sample data for the given language.
852 @param aGlyphCodes On success, holds an array of glyph codes, to be freed by the caller.
853 @param aNumGlyphCodes On success, holds the count of the glyph code array.
854 @leave KErrNotFound if the test data cannot be found or is empty in the config file.
856 void CTFbsGlyphData::LoadConfigSampleDataL(CFbsFont* aFont, TTestLanguage aLanguage, TBool aLongData, TUint*& aGlyphCodes, TInt& aNumGlyphCodes)
858 // The name of the section in the config file to look-up the sample data
859 _LIT(KConfigFileSampleData, "GlyphDataSampleText");
861 TBuf<32> keyName = ConfigKeyNameL(aLanguage, aLongData);
863 // Setup the converter to use the passed font.
864 iCharCodeConverter->UseFontL(aFont);
866 // Load the sample string data from the config file.
868 TESTL(GetStringFromConfig(KConfigFileSampleData, keyName, sampleText));
869 aNumGlyphCodes = sampleText.Length();
870 if (aNumGlyphCodes <= 0)
872 User::Leave(KErrNotFound);
874 aGlyphCodes = new(ELeave) TUint[aNumGlyphCodes];
875 for (TInt code = 0; code < aNumGlyphCodes; ++code)
877 aGlyphCodes[code] = iCharCodeConverter->GlyphCodeL(sampleText[code]);
882 Creates the name of the key to look for in the config file for the test
883 with the specified parameters.
884 @param aLanguage The language the test will use.
885 @param aLongData Whether to use long or short sample data.
886 @return A descriptor value of the language.
887 @leave KErrNotSupported if aLanguage is not recognised.
889 TBufC<32> CTFbsGlyphData::ConfigKeyNameL(TTestLanguage aLanguage, TBool aLongData)
891 if (aLanguage < 0 || aLanguage > 1)
893 User::Leave(KErrNotSupported);
895 TBuf<32> langName[2];
896 langName[ETestLanguageLatin].Append(_L("Latin"));
897 langName[ETestLanguageHindi].Append(_L("Hindi"));
898 langName[aLanguage].Append((aLongData) ? _L("Long") : _L("Short"));
899 return langName[aLanguage];
904 Utiltiy class for providing fonts for the performance tests.
907 CTFontFactory::CTFontFactory()
911 CTFontFactory::~CTFontFactory()
918 @return A new Font Factory ready to create fonts.
920 CTFontFactory* CTFontFactory::NewLC()
922 CTFontFactory* fontFactory = new (ELeave) CTFontFactory();
923 CleanupStack::PushL(fontFactory);
924 fontFactory->iTs = static_cast<CFbsTypefaceStore*>(CFbsTypefaceStore::NewL(NULL));
929 Creates a number of fonts for use by tests. All the fonts are created up-front so
930 that NextFont() can be called as a very lightweight call, so it can be used inside
931 tests with minimal impact.
932 Once fonts are created, the factory must not be destroyed until the fonts it created
934 @param aLanaugeMask Which language needs to be supported by the returned fonts.
935 @param aNumFonts The number of fonts to create
936 @param aStartSizeInPixels The lower bound font height of the fonts that are created. All
937 fonts will be at least as big as this value.
939 void CTFontFactory::CreateFontsL(TTestLanguage aLanguageMask, TInt aNumFonts, TInt aStartSizeInPixels)
943 RArray <TPtrC> typefaceNames;
944 CleanupClosePushL(typefaceNames);
945 switch(aLanguageMask)
947 case ETestLanguageHindi:
948 User::LeaveIfError(typefaceNames.Reserve(1));
949 typefaceNames.Append(_L("Devanagari OT Eval"));
951 case ETestLanguageLatin:
952 User::LeaveIfError(typefaceNames.Reserve(3));
953 typefaceNames.Append(_L("DejaVu Sans Condensed"));
954 typefaceNames.Append(_L("DejaVu Serif"));
955 typefaceNames.Append(_L("DejaVu Sans Mono"));
958 User::Leave(KErrNotSupported);
960 const TInt KNumTypefaces = typefaceNames.Count();
962 iFont = new CFbsFont*[aNumFonts];
963 for (TInt count = 0; count < aNumFonts; ++count)
965 // After every KNumTypefaces font, increase size by 5.
966 TInt size = aStartSizeInPixels + (5 *(count / KNumTypefaces));
967 TPtrC typefaceName = typefaceNames[count % KNumTypefaces];
968 TFontSpec fontSpec(typefaceName, size);
969 User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont[count], fontSpec));
973 CleanupStack::PopAndDestroy(1); // typefaceNames
976 Releases all created fonts and frees associated memory.
978 void CTFontFactory::ReleaseFonts()
980 for (TInt font = 0; font < iNumFonts; ++font)
982 iTs->ReleaseFont(iFont[font]);
990 @return The next font to be used. If it reaches the last font, the next font will
991 cycle back around to the first font.
993 CFbsFont* CTFontFactory::NextFont()
995 return iFont[++iCurFont%iNumFonts];