Update contrib.
1 // Copyright (c) 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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <test/tefunit.h> // for ASSERT macros
22 #include <e32msgqueue.h>
24 #include <test/tprofiler.h>
25 #include <test/egltestcommonprocess.h>
26 #include <test/egltestcommonconversion.h>
27 #include <test/egltestcommoninisettings.h>
29 #include "egltest_benchmark_sgimage.h"
31 //In general, there is no checking of the returned errors for the API we will be profiling
32 //we assume that the basic operations will just work, as they have been tested in many other places
33 //we don’t want error checking to interfere with the profiling itself
34 //to enable error checking, uncomment the macro below
35 //#define ENABLE_CHECKING_WHILST_PROFILING 1
37 _LIT(KBenchmarkSection, "Benchmark");
39 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
40 const TInt KBenchmarkDrawImageThreshold = 5; //semi-arbitrary number which signifies deviation in percentage between min and max number of image drawing
44 #define ENABLE_BENCHMARK_VERBOSE_LOGGING 1
46 //data will be used to cleanup VgImages if leaving occurs
47 NONSHARABLE_CLASS(CVgImageDeleteData) : public CBase
50 CVgImageDeleteData(VGImage*& aVgImages, TInt aNumVgImages) :
52 iNumVgImages(aNumVgImages)
55 ~CVgImageDeleteData();
57 VGImage*& iVgImages;//the ownership will be transferred and cleanup function will destroy this array
61 CVgImageDeleteData::~CVgImageDeleteData()
65 for(TInt count=iNumVgImages-1; count >= 0; --count)
67 vgDestroyImage(iVgImages[count]);
73 //data will be used to cleanup RSgImages if leaving occurs
74 NONSHARABLE_CLASS(CSgImageDeleteData) : public CBase
77 CSgImageDeleteData(RSgImage*& aSgImages, TInt aNumSgImages) :
79 iNumSgImages(aNumSgImages)
82 ~CSgImageDeleteData();
84 RSgImage*& iSgImages;//the ownership will be transferred and cleanup function will destroy this array
88 CSgImageDeleteData::~CSgImageDeleteData()
92 for(TInt count=iNumSgImages-1; count >= 0; --count)
94 iSgImages[count].Close();
100 //data will be used to cleanup EGLImages if leaving occurs
101 NONSHARABLE_CLASS(CEglImageDeleteData) : public CBase
104 CEglImageDeleteData(CEglTestStep& aImageBaseStep,
105 EGLImageKHR*& aEglImages, EGLDisplay& aDisplay, TInt aNumEglImages) :
106 iImageBaseStep(aImageBaseStep), iEglImages(aEglImages), iDisplay(aDisplay), iNumEglImages(aNumEglImages)
109 ~CEglImageDeleteData();
111 CEglTestStep& iImageBaseStep; //not owned by this object
112 EGLImageKHR*& iEglImages; //the ownership will be transferred and cleanup function will destroy this array
113 EGLDisplay iDisplay; //not owned by this object
117 CEglImageDeleteData::~CEglImageDeleteData()
121 CTestEglSession* eglSession = iImageBaseStep.GetEglSess();
122 for(TInt count=iNumEglImages-1; count >= 0; --count)
124 eglSession->DestroyEGLImage( iDisplay, iEglImages[count]);
126 delete [] iEglImages;
130 CEglTest_Benchmark_Base::~CEglTest_Benchmark_Base()
135 TVerdict CEglTest_Benchmark_Base::doTestStepPreambleL()
137 TVerdict verdict = CEglTestStep::doTestStepPreambleL();
138 iProfiler = CTProfiler::NewL(*this);
139 //read all parameters from config
140 CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
141 CleanupStack::PushL(iniParser);
142 iNumIterations = iniParser->GetNumberOfIterations(KBenchmarkSection);
145 ERR_PRINTF1(_L("The number iterations is not specified in INI file, the test will not be executed!"));
146 User::Leave(KErrArgument);
149 iImageSize = iniParser->GetImageSize(KBenchmarkSection);
150 if(iImageSize == TSize(0,0))
152 ERR_PRINTF1(_L("The image size whether is not specified in INI file or is TSize(0,0), the test will not be executed!"));
153 User::Leave(KErrArgument);
155 iPixelFormat = iniParser->GetPixelFormat(KBenchmarkSection, 0);
156 if(iPixelFormat == EUidPixelFormatUnknown)
158 ERR_PRINTF1(_L("The image pixel format is not specified in INI file, the test will not be executed!"));
159 User::Leave(KErrArgument);
161 CleanupStack::PopAndDestroy(iniParser);
162 INFO_PRINTF5(_L("**** The test will be run in following configuration: number of iterations %d, image size (%d, %d), image pixel format 0X%X"), iNumIterations, iImageSize.iWidth, iImageSize.iHeight, iPixelFormat);
166 TVerdict CEglTest_Benchmark_Base::doTestStepPostambleL()
168 delete iProfiler; //we need to delete here to keep happy heap checking in the base class
170 return CEglTestStep::doTestStepPostambleL();
176 @SYMTestCaseID GRAPHICS-EGL-0434
183 Performance test - Creating and destroying VGImage
185 Creating regular VGImage
186 Init EGL, create context and surface
189 Create VGImage[i] with size: 50x50 and format: VG_sARGB_8888_PRE
190 Stop timer and record time
192 Record average time of creating VGImage
194 Closing regular VGImage
198 Stop timer and record time
200 Record average time of destroying VGImage
201 Destroy context, surface and terminate EGL
203 Creating VGImage from uninitialized RSgImage
205 Construct TSgImageInfo object with
207 • PixelFormat: ESgPixelFormatARGB_8888_PRE
208 • Usage: ESgUsageBitOpenVgImage;
212 Create RSgImage[i] with arguments TSgImageInfo but without initialized data
213 Stop timer and record time
216 Create an EGLImage[i] from the RSgImage[i]
217 Stop timer and record time
220 Create a VGImage[i] from the EGLImage[i]
221 Stop timer and record time
223 Record total time of RSgImage[i], EGLImage[i] and VGImage[i] creation
225 Record average creation time of RSgImage, EGLImage, VGImage and the whole RSgImage-EGLImage-VGImage chain
227 Destroying VGImage from RSgImage
231 Stop timer and record time
235 Stop timer and record time
239 Stop timer and record time
241 Record total time for closing VGImage[i], EGLImage[i] and RSgImage[i]
243 Record average closing time of RSgImage, EGLImage, VGImage, and the whole
244 VGImage-EGLImage-RSgImage chain
246 Creating VGImage from initialized RSgImage
249 Create RSgImage[i] with arguments TSgImageInfo a stride of 200 and a pointer to a
250 data array of size 10000 bytes
251 Stop timer and record time
254 Create an EGLImage[i] from the RSgImage[i]
255 Stop timer and record time
258 Create a VGImage[i] from the EGLImage[i]
259 Stop timer and record time
261 Record total time for RSgImage[i], EGLImage[i] and VGImage[i] creation
263 Record average creation time of RSgImage, EGLImage, VGImage and the whole
264 RSgImage-EGLImage-VGImage chain
265 Close all VGImages, EGLImages and RSgImages
268 @SYMTestExpectedResults
269 The creation of RSgImage, EGLImage and VGImage must return no error.
270 The average time shall be made available in an easy-to-use format for further
271 analysis and comparison.
273 TVerdict CEglTest_Benchmark_CreateCloseImage::doTestStepL()
275 SetTestStepID(_L("GRAPHICS-EGL-0434"));
276 INFO_PRINTF1(_L("CEglTest_Benchmark_CreateCloseImage::doTestStepL"));
278 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
279 INFO_PRINTF1(_L("CEglTest_Benchmark_CreateCloseImage can only be run with SgImage-Lite"));
281 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KVG_KHR_EGL_image | KEGL_KHR_image_pixmap);
284 // The extension is not supported
286 CloseTMSGraphicsStep();
287 return TestStepResult();
290 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
293 iEglSess->InitializeL();
294 iEglSess->OpenSgDriverL();
295 //----create pixmap and make context curent
296 TSgImageInfo imageInfo;
297 imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
298 imageInfo.iPixelFormat = iPixelFormat;
299 imageInfo.iSizeInPixels = iImageSize;
300 //create a dummy surface and context for the purpose of enabling use of VG
301 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, CTestEglSession::EResourceCloseSgImageLate);
303 //Creating regular VGImages
304 //Create an array of VGImages and push them into cleanup stack
305 //vgImageDeleteData takes ownership of the VGImages array.
306 //If leaving occurs or this object is destroyed from the cleanup stack
307 //it will delete all images and then the array
308 VGImageFormat vgPixelFormat = EglTestConversion::PixelFormatToVgFormat(iPixelFormat);
309 VGImage* vgImages = NULL;
310 CVgImageDeleteData* vgImageDeleteData = new (ELeave) CVgImageDeleteData(vgImages, iNumIterations);
311 CleanupStack::PushL(vgImageDeleteData);
312 vgImages = new (ELeave)VGImage[iNumIterations];
313 //------- start profiling
314 iProfiler->InitResults();
315 for(TInt count=iNumIterations - 1; count >= 0; --count)
317 //we will use VG_IMAGE_QUALITY_NONANTIALIASED flag to avoid OpenVG making the quality improvements
318 //at the expense of performance (for instance to create an extra buffer)
319 vgImages[count] = vgCreateImage(vgPixelFormat, iImageSize.iWidth, iImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
320 //we will check the images later, to avoid interfering with the profiler
321 iProfiler->MarkResultSetL();
323 iProfiler->ResultsAnalysis(_L("Creating regular VGImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
325 //check that we created all VgImages
326 for(TInt count=iNumIterations - 1; count >= 0; --count)
328 ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
330 //Closing regular VGImage
331 iProfiler->InitResults();
332 for(TInt count=iNumIterations-1; count >= 0; --count)
334 vgDestroyImage(vgImages[count]);
335 iProfiler->MarkResultSetL();
337 iProfiler->ResultsAnalysis(_L("Closing regular VGImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
339 //--- Creating VGImage from uninitialized RSgImage
340 //Create an array of SgImages and push them into cleanup stack
341 //sgImageData takes ownership of the SgImages array.
342 //If leaving occurs or this object is destroyed from the cleanup stack
343 //it will delete all images and then the array
344 imageInfo.iUsage = ESgUsageBitOpenVgImage;
345 RSgImage* sgImages = NULL;
346 CSgImageDeleteData* sgImageData = new (ELeave)CSgImageDeleteData(sgImages, iNumIterations);
347 CleanupStack::PushL(sgImageData);
348 sgImages = new (ELeave) RSgImage[iNumIterations];
350 iProfiler->InitResults();
351 for(TInt count=iNumIterations-1; count >= 0; --count)
353 const TInt res = sgImages[count].Create(imageInfo, NULL);
354 #ifdef ENABLE_CHECKING_WHILST_PROFILING
355 TESTL(res == KErrNone);
357 iProfiler->MarkResultSetL();
359 iProfiler->ResultsAnalysis(_L("Creating uninitialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
361 //check that we created all sgImages successfully
362 for(TInt count=iNumIterations - 1; count >= 0; --count)
364 TESTL(!sgImages[count].IsNull());
367 //Create an array of EglImages and push them into cleanup stack
368 //eglImageDeleteData takes ownership of the EglImages array.
369 //If leaving occurs or this object is destroyed from the cleanup stack
370 //it will delete all images and then the array
371 EGLImageKHR* eglImages = NULL;
372 CEglImageDeleteData* eglImageDeleteData = new (ELeave)CEglImageDeleteData(*this, eglImages, iDisplay, iNumIterations);
373 CleanupStack::PushL(eglImageDeleteData);
374 eglImages = new (ELeave) EGLImageKHR[iNumIterations];
376 iProfiler->InitResults();
377 for(TInt count=iNumIterations-1; count >= 0; --count)
378 {//we will use preserved flag as sgImage supposedly has some content
379 eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[count],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
380 iProfiler->MarkResultSetL();
382 iProfiler->ResultsAnalysis(_L("Creating EGLImage from uninitialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
384 //check that we created all EglImages successfully
385 for(TInt count=iNumIterations-1; count >= 0; --count)
387 ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)
390 iProfiler->InitResults();
391 for(TInt count=iNumIterations-1; count >= 0; --count)
393 vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
394 iProfiler->MarkResultSetL();
396 iProfiler->ResultsAnalysis(_L("Creating VGImage from EGLImage, which in turn based on uninitialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
398 //check that we created all sgImages successfully
399 for(TInt count=iNumIterations-1; count >= 0; --count)
401 ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
404 //Destroying VGImage/EGLImage/RSgImages
405 iProfiler->InitResults();
406 for(TInt count=iNumIterations-1; count >= 0; --count)
408 vgDestroyImage(vgImages[count]);
409 iProfiler->MarkResultSetL();
411 iProfiler->ResultsAnalysis(_L("Destroying VGImage which based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
413 iProfiler->InitResults();
414 for(TInt count=iNumIterations-1; count >= 0; --count)
416 const TBool res = iEglSess->DestroyEGLImage(iDisplay, eglImages[count]);
417 #ifdef ENABLE_CHECKING_WHILST_PROFILING
420 iProfiler->MarkResultSetL();
422 iProfiler->ResultsAnalysis(_L("Destroying EGLImage which in turn based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
424 iProfiler->InitResults();
425 for(TInt count=iNumIterations-1; count >= 0; --count)
427 sgImages[count].Close();
428 iProfiler->MarkResultSetL();
430 iProfiler->ResultsAnalysis(_L("Closing RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
432 //Creating initialized VGImage from initialized RSgImage
433 const TInt KDataStride = iImageSize.iWidth * EglTestConversion::BytePerPixel(iPixelFormat);
434 const TInt KDataSizeInByte = KDataStride * iImageSize.iHeight;
435 TInt* data = new (ELeave) TInt[KDataSizeInByte];
436 User::LeaveIfNull(data);
437 CleanupStack::PushL(data);
439 Mem::Fill(data, KDataSizeInByte / 2, 0xff);
440 Mem::FillZ(data + KDataSizeInByte / 2, KDataSizeInByte / 2);
442 iProfiler->InitResults();
443 for(TInt count=iNumIterations-1; count >= 0; --count)
445 const TInt res = sgImages[count].Create(imageInfo, data, KDataStride);
446 #ifdef ENABLE_CHECKING_WHILST_PROFILING
447 TESTL(res == KErrNone);
449 iProfiler->MarkResultSetL();
451 iProfiler->ResultsAnalysis(_L("Creating initialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
453 //check that we created all sgImages successfully
454 for(TInt count=iNumIterations-1; count >= 0; --count)
456 TESTL(!sgImages[count].IsNull());
459 iProfiler->InitResults();
460 for(TInt count=iNumIterations-1; count >= 0; --count)
461 {//we will use preserved flag as sgImage supposedly has some content
462 eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
463 &sgImages[count], const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
464 iProfiler->MarkResultSetL();
466 iProfiler->ResultsAnalysis(_L("Creating EGLImage from initialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
468 //check that we created all EglImages successfully
469 for(TInt count=iNumIterations-1; count >= 0; --count)
471 ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)
474 iProfiler->InitResults();
475 for(TInt count=iNumIterations-1; count >= 0; --count)
477 vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
478 iProfiler->MarkResultSetL();
480 iProfiler->ResultsAnalysis(_L("Creating VGImage from EGLImage which in turn based on initialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
482 //check that we created all VgImages successfully
483 for(TInt count=iNumIterations-1; count >= 0; --count)
485 ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
488 CleanupStack::PopAndDestroy(data);
489 //Destroying VGImage/EGLImage/RSgImages
490 //no need to profile as we have already done this before
491 CleanupStack::PopAndDestroy(3, vgImageDeleteData); // vgImageDeleteData, sgImageData, eglImageDeleteData
494 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
496 CloseTMSGraphicsStep();
497 return TestStepResult();
501 @SYMTestCaseID GRAPHICS-EGL-0435
508 Performance test – Creating and destroying VGImage from an RSgImage via Open
510 Environmental settings:
511 • Image Size: w50 h50
513 • Pixel format ESgPixelFormatARGB_8888_PRE
514 • Number of benchmark iteration: N
516 The method of creation of the RSgImage is similar to the case taken from GRAPHICS-EGL-RSGIMAGE_LITE-0406
521 Spawn a client process B, passing in the drawable ID of the RSgImage
522 Wait for process B to exit
529 Stop timer and record time
532 Create an EGLImage[i] from the RSgImage[i]
533 Stop timer and record time
536 Create a VGImage[i] from the EGLImage[i]
537 Stop timer and record time
539 Record total time of RSgImage[i] open and EGLImage[i] and VGImage[i] creation
541 Record average opening time of RSgImage, and average creation time of EGLImage,
542 VGImage and the whole RSgImage-EGLImage-VGImage chain
546 Stop timer and record time
550 Stop timer and record time
554 Stop timer and record time
556 Record total time for closing VGImage[i], EGLImage[i] and RSgImage[i]
558 Record average closing time of RSgImage, EGLImage, VGImage, and the whole VGImage-EGLImage-RSgImage chain
563 @SYMTestExpectedResults
564 The creation/opening of RSgImage, EGLImage and VGImage must return no error.
565 The average time shall be made available in an easy-to-use format
566 for further analysis and comparison. All allocated image memory should be freed
568 TVerdict CEglTest_Benchmark_Multi_Process_CreateCloseImage::doTestStepL()
570 SetTestStepID(_L("GRAPHICS-EGL-0435"));
571 SetTestStepName(KBenchmark_Multi_Process_CreateCloseImage);
572 INFO_PRINTF1(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage::doTestStepL"));
574 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
575 INFO_PRINTF1(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage can only be run with SgImage-Lite"));
577 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KVG_KHR_EGL_image | KEGL_KHR_image_pixmap);
580 // The extension is not supported
582 CloseTMSGraphicsStep();
583 return TestStepResult();
586 // launch 2 processes
587 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
589 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
591 CloseTMSGraphicsStep();
592 return TestStepResult();
595 void CEglTest_Benchmark_Multi_Process_CreateCloseImage::doProcessFunctionL(TInt aIdx)
597 INFO_PRINTF2(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage::doProcessFunctionL, Process %d"),aIdx);
598 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
600 CreateEglSessionL(aIdx);
601 iEglSess->InitializeL();
602 iEglSess->OpenSgDriverL();
604 TSgImageInfo imageInfo;
605 imageInfo.iUsage = ESgUsageBitOpenVgImage;
606 imageInfo.iPixelFormat = iPixelFormat;
607 imageInfo.iSizeInPixels = iImageSize;
608 RArray<TSgDrawableId> sgIdImageList;
610 //Create an array of SgImages and push them into cleanup stack
611 //sgImageData takes ownership of the SgImages array.
612 //If leaving occurs or this object is destroyed from the cleanup stack
613 //it will delete all images and then the array
614 RSgImage* sgImages = NULL;
615 CSgImageDeleteData* sgImageData = new (ELeave)CSgImageDeleteData(sgImages, iNumIterations);
616 CleanupStack::PushL(sgImageData);
617 sgImages = new (ELeave) RSgImage[iNumIterations];
619 RMsgQueue<TSgDrawableId> messageQueue;
620 User::LeaveIfError(messageQueue.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
621 CleanupClosePushL(messageQueue);
623 //create iNumIterations number of SgImages in one process and send them over to the second process
624 INFO_PRINTF3(_L("Process %d, Start sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
627 for(TInt count=0; count < iNumIterations; ++count)
629 const TInt res = sgImages[count].Create(imageInfo, NULL);
630 TESTL(res == KErrNone);
631 messageQueue.SendBlocking(sgImages[count].Id());
636 for(TInt count=0; count < iNumIterations; ++count)
638 TSgDrawableId sgImageId;
639 messageQueue.ReceiveBlocking(sgImageId);
640 sgIdImageList.AppendL(sgImageId);
643 INFO_PRINTF3(_L("Process %d, Finish sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
645 CleanupStack::PopAndDestroy(&messageQueue);
647 // Wait for both processes to reach this point
648 // This is to be sure that there is no context
649 //switching whilst the profiling occurs
653 imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
654 //create a dummy surface and context for the purpose of enabling use of VG
655 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, CTestEglSession::EResourceCloseSgImageLate);
657 iProfiler->InitResults();
658 for(TInt count=iNumIterations-1; count >= 0; --count)
660 const TInt res = sgImages[count].Open(sgIdImageList[count]);
661 #ifdef ENABLE_CHECKING_WHILST_PROFILING
662 TESTL(res == KErrNone);
664 iProfiler->MarkResultSetL();
666 iProfiler->ResultsAnalysis(_L("Open RSgImage from another process"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
668 //check that we created all sgImages successfully
669 for(TInt count=iNumIterations-1; count >= 0; --count)
671 TESTL(!sgImages[count].IsNull());
674 //Create an array of EglImages and push them into cleanup stack
675 //eglImageDeleteData takes ownership of EglImages array.
676 //If leaving occurs or this object is destroyed from the cleanup stack
677 //it will delete all images and then the array
678 EGLImageKHR* eglImages = NULL;
679 CEglImageDeleteData* eglImageDeleteData = new (ELeave)CEglImageDeleteData(*this, eglImages, iDisplay, iNumIterations);
680 CleanupStack::PushL(eglImageDeleteData);
681 eglImages = new (ELeave) EGLImageKHR[iNumIterations];
683 iProfiler->InitResults();
684 for(TInt count=iNumIterations-1; count >= 0; --count)
685 {//we will use preserved flag as sgImage supposedly has some content
686 eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[count],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
687 iProfiler->MarkResultSetL();
689 iProfiler->ResultsAnalysis(_L("Creating EGLImage from RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
691 //check that we created all EglImages successfully
692 for(TInt count=iNumIterations-1; count >= 0; --count)
694 ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)
697 //Create an array of VGImages and push them into cleanup stack
698 //vgImageDeleteData takes ownership of VgImages array.
699 //If leaving occurs or this object is destroyed from the cleanup stack
700 //it will delete all images and then the array
701 VGImage* vgImages = NULL;
702 CVgImageDeleteData* vgImageDeleteData = new (ELeave) CVgImageDeleteData(vgImages, iNumIterations);
703 CleanupStack::PushL(vgImageDeleteData);
704 vgImages = new (ELeave) VGImage[iNumIterations];
706 iProfiler->InitResults();
707 for(TInt count=iNumIterations-1; count >= 0; --count)
709 vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
710 iProfiler->MarkResultSetL();
712 iProfiler->ResultsAnalysis(_L("Creating VGImage from EGLImage, which in turn based on SgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
714 //check that we created all VgImages successfully
715 for(TInt count=iNumIterations-1; count >= 0; --count)
717 ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
720 sgIdImageList.Reset();
722 //Destroying VGImage/EglImage/RSgImages
723 iProfiler->InitResults();
724 for(TInt count=iNumIterations-1; count >= 0; --count)
726 vgDestroyImage(vgImages[count]);
727 iProfiler->MarkResultSetL();
729 iProfiler->ResultsAnalysis(_L("Destroying VGImage based on EGLImage which in turn based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
731 iProfiler->InitResults();
732 for(TInt count=iNumIterations-1; count >= 0; --count)
734 const TBool res = iEglSess->DestroyEGLImage(iDisplay, eglImages[count]);
735 #ifdef ENABLE_CHECKING_WHILST_PROFILING
736 ASSERT_EGL_TRUE(res);
738 iProfiler->MarkResultSetL();
740 iProfiler->ResultsAnalysis(_L("Destroying EGLImage which based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
742 iProfiler->InitResults();
743 for(TInt count=iNumIterations-1; count >= 0; --count)
745 sgImages[count].Close();
746 iProfiler->MarkResultSetL();
748 iProfiler->ResultsAnalysis(_L("Closing RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);
749 CleanupStack::PopAndDestroy(2, eglImageDeleteData); //eglImageDeleteData, vgImageDeleteData
752 // Wait for both processes to reach this point
754 CleanupStack::PopAndDestroy(sgImageData);
756 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
761 @SYMTestCaseID GRAPHICS-EGL-0436
768 Performance test - Drawing of VGImage
771 Compare the relative speed of drawing a regular pre-existing VGImage with the
772 speed of mapping in a VGImage (starting with a drawable id) and then drawing that.
775 Environmental settings:
776 • Image Size: w50 h50
778 • Pixel format ESgPixelFormatARGB_8888_PRE
779 • Number of benchmark iteration: N (may vary depending on hardware capacity)
781 From the main test process:
782 Spawn two processes A and B
785 Construct TSgImageInfo object with
787 • PixelFormat: ESgPixelFormatARGB_8888_PRE
788 • Usage: ESgUsageBitOpenVgImage;
790 Creation of the RSgImages:
792 Form pixel data in such way that there will be a mixture of opaque and transparent pixels.
793 At least one coordinate of the opaque pixel will be unique for any iteration.
794 Creating RSgImage with initialized data, size: 50x50 and format: VG_sARGB_8888_PRE.
795 Send RSgImage drawableID to process B
797 Close all RSgImages after they will have been opened in process B
798 Close RSgDriver after process B finishes with benchmark measurement.
803 Receive and store drawableID[i] from process A
806 Init EGL, create context and pixmap surface. Make the surface current.
807 Creating regular VGImage:
809 Create VGImage[i] with size: 50x50 and format: VG_sARGB_8888_PRE
810 SetSubData for VGImage[i] with the same data which were supplied on RSgImage creation
813 Draw regular VGImage:
819 Stop timer and record time
821 Complete all outstanding requests on the current context (vgFinish)
822 Record max, min, average drawing time of VGImage
823 Check that deviation between max and min time doesn’t exceed 5% (max – min / mean) < 0.05
825 Destroy all regular VGImages
828 Mapping in VGImage from initialized RSgImage and perform drawing:
832 Open RSgImage[i] with drawableID[i]
833 Create an EGLImage[i] from the RSgImage[i]
834 Create a VGImage[i] from the EGLImage[i]
837 Complete all outstanding requests on the current context (vgFinish)
838 Stop timer and record time
840 Record max, min, average mapping and drawing time of VGImage
841 Check that deviation between max and min time doesn’t exceed 5% (max – min / mean) < 0.05
843 Destroy context, surface
844 Close all VGImages, EGLImages and RSgImages
845 Terminate Egl environment
848 @SYMTestExpectedResults
849 The creation of RSgImage, EGLImage and VGImage must return no error.
850 The drawing speed of regular VGImage and mapping VGImage (starting from drawable id)
851 with following draw is made available in an easy-to-use format for further analysis and
854 TVerdict CEglTest_Benchmark_DrawImage::doTestStepL()
856 SetTestStepID(_L("GRAPHICS-EGL-0436"));
857 SetTestStepName(KBenchmark_DrawImage);
858 INFO_PRINTF1(_L("CEglTest_Benchmark_DrawImage::doTestStepL"));
860 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
861 INFO_PRINTF1(_L("CEglTest_Benchmark_DrawImage can only be run with SgImage-Lite"));
863 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KVG_KHR_EGL_image | KEGL_KHR_image_pixmap);
866 // launch 2 processes
867 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
869 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
872 CloseTMSGraphicsStep();
873 return TestStepResult();
876 void CEglTest_Benchmark_DrawImage::doProcessFunctionL(TInt aIdx)
878 INFO_PRINTF2(_L("CEglTest_Benchmark_DrawImage::doProcessFunctionL, Process %d"),aIdx);
879 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
881 CreateEglSessionL(aIdx);
882 iEglSess->InitializeL();
883 iEglSess->OpenSgDriverL();
885 TSgImageInfo imageInfo;
886 imageInfo.iUsage = ESgUsageBitOpenVgImage;
887 imageInfo.iPixelFormat = iPixelFormat;
888 imageInfo.iSizeInPixels = iImageSize;
889 RArray<TSgDrawableId> sgIdImageList;
891 const TInt KNumAttempt = 5;
892 const TInt KNumImagesToDraw = iNumIterations;
893 //Create an array of SgImages and push them into cleanup stack
894 //sgImageData takes ownership of the SgImages array.
895 //If leaving occurs or this object is destroyed from the cleanup stack
896 //it will delete all images and then the array
897 RSgImage* sgImages = NULL;
898 CSgImageDeleteData* sgImageData = new (ELeave)CSgImageDeleteData(sgImages, KNumImagesToDraw);
899 CleanupStack::PushL(sgImageData);
900 sgImages = new (ELeave) RSgImage[KNumImagesToDraw];
902 // the message queue will be used to pass image IDs across process boundary
903 RMsgQueue<TSgDrawableId> messageQueue;
904 User::LeaveIfError(messageQueue.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
905 CleanupClosePushL(messageQueue);
907 //create iNumIterations * KNumAttempt number of SgImages in one process and send them over to the second process
908 INFO_PRINTF3(_L("Process %d, Start sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
911 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
912 for(TInt index=0; index < KNumImagesToDraw; ++index)
914 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, iImageSize, index);
915 CleanupStack::PushL(bitmap);
916 ASSERT_EQUALS(sgImages[index].Create(imageInfo, bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
917 messageQueue.SendBlocking(sgImages[index].Id());
918 CleanupStack::PopAndDestroy(bitmap);
923 for(TInt index=0; index < KNumImagesToDraw; ++index)
925 TSgDrawableId sgImageId;
926 messageQueue.ReceiveBlocking(sgImageId);
927 sgIdImageList.AppendL(sgImageId);
930 CleanupStack::PopAndDestroy(&messageQueue);
931 INFO_PRINTF3(_L("Process %d, Finish sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
932 //We expect to reach this point from both processes simultaneously
933 //this is because ReceiveBlocking/SendBlocking are synchronous
937 imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
938 //create a dummy surface and context for the purpose of enabling use of VG
939 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, CTestEglSession::EResourceCloseSgImageLate);
941 //Creating regular VGImages
942 //Create an array of VGImages and push them into cleanup stack
943 //vgImageDeleteData takes ownership of the VGImages array.
944 //If leaving occurs or this object is destroyed from the cleanup stack
945 //it will delete all images and then the array
946 VGImageFormat vgPixelFormat = EglTestConversion::PixelFormatToVgFormat(iPixelFormat);
947 VGImage* vgImages = NULL;
948 CVgImageDeleteData* vgImageDeleteData = new (ELeave) CVgImageDeleteData(vgImages, KNumImagesToDraw);
949 CleanupStack::PushL(vgImageDeleteData);
950 vgImages = new (ELeave)VGImage[KNumImagesToDraw];
951 for(TInt index=KNumImagesToDraw - 1; index >= 0; --index)
953 //we will use VG_IMAGE_QUALITY_NONANTIALIASED flag to avoid OpenVG making the quality improvements
954 //at the expense of performance (for instance to create an extra buffer)
955 vgImages[index] = vgCreateImage(vgPixelFormat, iImageSize.iWidth, iImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
956 ASSERT_VG_TRUE(vgImages[index] != VG_INVALID_HANDLE);
958 TDisplayMode bitmapMode = EglTestConversion::VgFormatToDisplayMode(EglTestConversion::PixelFormatToVgFormat(iPixelFormat));
959 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, iImageSize, index);
960 CleanupStack::PushL(bitmap);
961 // Add pixel data to the VGImage reference from the bitmap reference.
962 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
963 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
964 TInt stride = bitmap->DataStride();
965 address += (iImageSize.iHeight - 1) * stride;
966 vgImageSubData(vgImages[index], address, -stride,
967 KDefaultSurfaceFormat, 0,0, iImageSize.iWidth, iImageSize.iHeight);
968 ASSERT_VG_ERROR(VG_NO_ERROR);
969 CleanupStack::PopAndDestroy(bitmap);
971 #ifdef ENABLE_BENCHMARK_VERBOSE_LOGGING
972 iProfiler->SetStoreResultInTimingOrder(ETrue);
974 //--------- start profiling
975 INFO_PRINTF1(_L("Profiling of drawing of the regular VG image"));
976 iProfiler->InitResults();
977 for(TInt count = KNumAttempt - 1; count >= 0; --count)
979 for(TInt index=iNumIterations - 1; index >= 0; --index)
981 vgDrawImage(vgImages[index]);
982 #ifdef ENABLE_CHECKING_WHILST_PROFILING
983 ASSERT_VG_ERROR(VG_NO_ERROR);
987 #ifdef ENABLE_CHECKING_WHILST_PROFILING
988 ASSERT_VG_ERROR(VG_NO_ERROR);
990 iProfiler->MarkResultSetL();
992 iProfiler->ResultsAnalysis(_L("Drawing of the regular VGImages"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), KNumAttempt);
993 #ifdef ENABLE_BENCHMARK_VERBOSE_LOGGING
994 iProfiler->ShowResultArrayInTimingOrder();
996 const TInt KDeviationRegular = ((((TReal)(iProfiler->TimeMax())) - iProfiler->TimeMin()) / (TReal)(iProfiler->Mean())) * 100;
997 INFO_PRINTF3(_L("Deviation in percentage between min and max number of images drawing ((TimeMax - TimeMin) / Mean * 100): %d, threshold: %d "), KDeviationRegular, KBenchmarkDrawImageThreshold);
998 if(KDeviationRegular > KBenchmarkDrawImageThreshold)
1000 //unfortunatelly EGL test framework currently ignores the error because this is a spawned process, and not
1001 // the main cteststep process. We could leave, but that would be too harsh in this situation
1002 WARN_PRINTF1(_L("***The deviation has exceeded threshold, the number of iteration needs to be increased!!!"));
1005 //--------- stop profiling
1008 for(TInt index=0; index < KNumImagesToDraw; index++)
1010 vgDestroyImage(vgImages[index]);
1011 vgImages[index]=VG_INVALID_HANDLE;
1012 ASSERT_VG_ERROR(VG_NO_ERROR);
1015 //Create an array of EglImages and push them into cleanup stack
1016 //eglImageDeleteData takes ownership of the EglImages array.
1017 //If leaving occurs or this object is destroyed from the cleanup stack
1018 //it will delete all images and then the array
1019 EGLImageKHR* eglImages = NULL;
1020 CEglImageDeleteData* eglImageDeleteData = new (ELeave)CEglImageDeleteData(*this, eglImages, iDisplay, KNumImagesToDraw);
1021 CleanupStack::PushL(eglImageDeleteData);
1022 eglImages = new (ELeave) EGLImageKHR[KNumImagesToDraw];
1024 //---------------start profiling
1025 INFO_PRINTF1(_L("Profiling of mapping in and drawing of the VG images with underlying RSgImage"));
1026 iProfiler->InitResults();
1027 for(TInt count = KNumAttempt - 1; count >= 0; --count)
1028 {//we will run KNumAttemt times in a row and check that the set of results is consistent,
1029 // i.e. deviation between max and min time doesn't exceed KBenchmarkDrawImageThreshold percentage
1031 for(TInt index=iNumIterations - 1; index >= 0; --index)
1033 #ifdef ENABLE_CHECKING_WHILST_PROFILING
1034 const TInt res = sgImages[index].Open(sgIdImageList[index]);
1035 TESTL(res == KErrNone);
1036 TESTL(!sgImages[index].IsNull());
1037 eglImages[index]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[index],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
1038 ASSERT_EGL_TRUE(eglImages[index] != EGL_NO_IMAGE_KHR)
1039 vgImages[index] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[index]);
1040 ASSERT_VG_TRUE(vgImages[index] != VG_INVALID_HANDLE);
1041 vgDrawImage(vgImages[index]);
1042 ASSERT_VG_ERROR(VG_NO_ERROR);
1044 const TInt res = sgImages[index].Open(sgIdImageList[index]);
1045 eglImages[index]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[index],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
1046 vgImages[index] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[index]);
1047 vgDrawImage(vgImages[index]);
1049 #endif //ENABLE_CHECKING_WHILST_PROFILING
1052 #ifdef ENABLE_CHECKING_WHILST_PROFILING
1053 ASSERT_VG_ERROR(VG_NO_ERROR);
1055 iProfiler->MarkResultSetAndSuspendL(); //mark the end of the iteration. The timer will not be resumed yet
1057 // Clean Sg/Vg/Egl images.
1058 // This is to ensure that expanding of the images will not impact measurement
1059 for(TInt index=iNumIterations - 1; index >= 0; --index)
1061 sgImages[index].Close();
1062 vgDestroyImage(vgImages[index]);
1063 vgImages[index] = VG_INVALID_HANDLE;
1064 iEglSess->DestroyEGLImage( iDisplay, eglImages[index]);
1065 eglImages[index] = EGL_NO_IMAGE_KHR;
1068 iProfiler->StartTimer();
1070 //----------------stop profiling
1072 const TInt KDeviation = ((((TReal)(iProfiler->TimeMax())) - iProfiler->TimeMin()) / (TReal)(iProfiler->Mean())) * 100;
1073 INFO_PRINTF3(_L("Deviation in percentage between min and max number of images drawing ((TimeMax - TimeMin) / Mean * 100): %d, threshold: %d "), KDeviation, KBenchmarkDrawImageThreshold);
1074 if(KDeviation > KBenchmarkDrawImageThreshold)
1076 //unfortunatelly EGL test framework currently ignores the error because this is a spawned process, and not
1077 // the main cteststep process. We could leave, but that would be too harsh in this situation
1078 WARN_PRINTF1(_L("***The deviation has exceeded threshold, the number of iteration needs to be increased!!!"));
1081 iProfiler->ResultsAnalysis(_L("Drawing VGImages with underlying RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), KNumAttempt);
1082 #ifdef ENABLE_BENCHMARK_VERBOSE_LOGGING
1083 iProfiler->ShowResultArrayInTimingOrder();
1085 sgIdImageList.Reset();
1088 //Introduce synchronization point here to make sure that RSgImages are not closed from the
1089 //first process while the second one is busy with benchmark measurement
1093 //Destroying VGImage/EGLImage/RSgImages
1094 //no need to profile as we have already done this before
1095 CleanupStack::PopAndDestroy(sgImageData); // sgImageData
1099 //Destroying VGImage/EGLImage/RSgImages
1100 //no need to profile as we have already done this before
1101 CleanupStack::PopAndDestroy(3, sgImageData); // sgImageData, vgImageDeleteData, eglImageDeleteData
1104 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE