egl/egltest/src/egltest_benchmark_sgimage.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 16:21:04 +0300
changeset 36 01a6848ebfd7
parent 0 5d03bc08d59c
child 33 25f95128741d
permissions -rw-r--r--
Revision: 201009 Kit: 201015

// Copyright (c) 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:
//

/**
 @file
 @test
*/

#include <test/tefunit.h> // for ASSERT macros
#include <e32msgqueue.h>

#include <test/tprofiler.h>
#include <test/egltestcommonprocess.h>
#include <test/egltestcommonconversion.h>
#include <test/egltestcommoninisettings.h>

#include "egltest_benchmark_sgimage.h"

//In general, there is no checking of the returned errors for the API we will be profiling
//we assume that the basic operations will just work, as they have been tested in many other places
//we don’t want error checking to interfere with the profiling itself 
//to enable error checking, uncomment the macro below 
//#define ENABLE_CHECKING_WHILST_PROFILING    1 

_LIT(KBenchmarkSection, "Benchmark");

#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
const TInt KBenchmarkDrawImageThreshold = 5; //semi-arbitrary number which signifies deviation in percentage between min and max number of image drawing
#endif


#define ENABLE_BENCHMARK_VERBOSE_LOGGING    1

//data will be used to cleanup VgImages if leaving occurs
NONSHARABLE_CLASS(CVgImageDeleteData) : public CBase
    {
public:
    CVgImageDeleteData(VGImage*& aVgImages, TInt aNumVgImages) :
        iVgImages(aVgImages),
        iNumVgImages(aNumVgImages)
        {
        }
    ~CVgImageDeleteData();
private:    
    VGImage*& iVgImages;//the ownership will be transferred and cleanup function will destroy this array
    TInt iNumVgImages;
    };

CVgImageDeleteData::~CVgImageDeleteData()
    {
    if(iVgImages)
        {
        for(TInt count=iNumVgImages-1; count >= 0; --count)
            {
            vgDestroyImage(iVgImages[count]);
            }
        delete [] iVgImages;
        }
    }

//data will be used to cleanup RSgImages if leaving occurs
NONSHARABLE_CLASS(CSgImageDeleteData) : public CBase
    {
public:
    CSgImageDeleteData(RSgImage*& aSgImages, TInt aNumSgImages) :
        iSgImages(aSgImages),
        iNumSgImages(aNumSgImages)
        {
        }
    ~CSgImageDeleteData();
private:    
    RSgImage*& iSgImages;//the ownership will be transferred and cleanup function will destroy this array
    TInt iNumSgImages;
    };

CSgImageDeleteData::~CSgImageDeleteData()
    {
    if(iSgImages)
        {
        for(TInt count=iNumSgImages-1; count >= 0; --count)
            {
            iSgImages[count].Close();
            }
        delete [] iSgImages;
        }
    }

//data will be used to cleanup EGLImages if leaving occurs
NONSHARABLE_CLASS(CEglImageDeleteData) : public CBase
    {
public:
    CEglImageDeleteData(CEglTestStep& aImageBaseStep, 
            EGLImageKHR*& aEglImages, EGLDisplay& aDisplay, TInt aNumEglImages) : 
        iImageBaseStep(aImageBaseStep), iEglImages(aEglImages), iDisplay(aDisplay), iNumEglImages(aNumEglImages)
        {
        }
    ~CEglImageDeleteData();
private:    
	CEglTestStep& iImageBaseStep; //not owned by this object
    EGLImageKHR*& iEglImages; //the ownership will be transferred and cleanup function will destroy this array
    EGLDisplay iDisplay; //not owned by this object
    TInt iNumEglImages;
    };

CEglImageDeleteData::~CEglImageDeleteData()
    {
    if(iEglImages)
        {
        CTestEglSession* eglSession = iImageBaseStep.GetEglSess(); 
        for(TInt count=iNumEglImages-1; count >= 0; --count)
            {    
            eglSession->DestroyEGLImage( iDisplay, iEglImages[count]);
            }
        delete [] iEglImages;
        }
    }

CEglTest_Benchmark_Base::~CEglTest_Benchmark_Base()
    {
    delete iProfiler;
    }

TVerdict CEglTest_Benchmark_Base::doTestStepPreambleL()
    {
    TVerdict verdict = CEglTestStep::doTestStepPreambleL();
    iProfiler = CTProfiler::NewL(*this);
    //read all parameters from config
    CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
    CleanupStack::PushL(iniParser);
    iNumIterations = iniParser->GetNumberOfIterations(KBenchmarkSection);
    if(!iNumIterations)
        {
        ERR_PRINTF1(_L("The number iterations is not specified in INI file, the test will not be executed!"));
        User::Leave(KErrArgument);      
        }
    
    iImageSize = iniParser->GetImageSize(KBenchmarkSection);
    if(iImageSize == TSize(0,0))
        {
        ERR_PRINTF1(_L("The image size whether is not specified in INI file or is TSize(0,0), the test will not be executed!"));
        User::Leave(KErrArgument);      
        }
    iPixelFormat = iniParser->GetPixelFormat(KBenchmarkSection, 0);
    if(iPixelFormat == EUidPixelFormatUnknown)
        {
        ERR_PRINTF1(_L("The image pixel format is not specified in INI file, the test will not be executed!"));
        User::Leave(KErrArgument);      
        }
    CleanupStack::PopAndDestroy(iniParser);
    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);
    return verdict;
    }

TVerdict CEglTest_Benchmark_Base::doTestStepPostambleL()
    {
    delete iProfiler; //we need to delete here to keep happy heap checking in the base class 
    iProfiler = NULL;
    return CEglTestStep::doTestStepPostambleL();
    }



/**
@SYMTestCaseID GRAPHICS-EGL-0434

@SYMTestPriority 1

@SYMPREQ 2637

@SYMTestCaseDesc
    Performance test - Creating and destroying VGImage
@SYMTestActions
Creating regular VGImage
Init EGL, create context and surface
For i = 0 to N
    Start timer
    Create VGImage[i] with size: 50x50 and format:  VG_sARGB_8888_PRE
    Stop timer and record time
End loop
Record average time of creating VGImage

Closing regular VGImage
For i = N to 0
    Start timer
    Destroy VGImage[i]
    Stop timer and record time
End loop
Record average time of destroying VGImage
Destroy context, surface and terminate EGL

Creating VGImage from uninitialized RSgImage
Open RSgDriver
Construct TSgImageInfo object with
•   Size: 50x50
•   PixelFormat: ESgPixelFormatARGB_8888_PRE
•   Usage: ESgUsageBitOpenVgImage;

For i = 0 to N
    Start timer
    Create RSgImage[i] with arguments TSgImageInfo but without initialized data
    Stop timer and record time

    Start timer
    Create an EGLImage[i] from the RSgImage[i]
    Stop timer and record time

    Start timer
    Create a VGImage[i] from the EGLImage[i]
    Stop timer and record time

    Record total time of  RSgImage[i], EGLImage[i] and VGImage[i] creation
End loop
Record average creation time of RSgImage, EGLImage, VGImage and the whole RSgImage-EGLImage-VGImage chain

Destroying VGImage from RSgImage
For i = N to 0
    Start timer
    Close VGImage[i]
    Stop timer and record time

    Start timer
    Close EGLImage[i]
    Stop timer and record time

    Start timer
    Close RSgImage[i]
    Stop timer and record time

    Record total time for closing VGImage[i], EGLImage[i] and RSgImage[i]
End loop
Record average closing time of RSgImage, EGLImage, VGImage, and the whole 
VGImage-EGLImage-RSgImage chain

Creating VGImage from initialized RSgImage
For i = 0 to N
    Start timer
    Create RSgImage[i] with arguments TSgImageInfo a stride of 200 and a  pointer to a 
    data array of size 10000 bytes
    Stop timer and record time

    Start timer
    Create an EGLImage[i] from the RSgImage[i]
    Stop timer and record time

    Start timer
    Create a VGImage[i] from the EGLImage[i]
    Stop timer and record time

    Record total time for RSgImage[i], EGLImage[i] and VGImage[i] creation
End loop
Record average creation time of RSgImage, EGLImage, VGImage and the whole 
RSgImage-EGLImage-VGImage chain
Close all VGImages, EGLImages and RSgImages
Close RSgDriver

@SYMTestExpectedResults
The creation of RSgImage, EGLImage and VGImage must return no error. 
The average time shall be made available in an easy-to-use format for further 
analysis and comparison.
*/
TVerdict CEglTest_Benchmark_CreateCloseImage::doTestStepL()
    {
    SetTestStepID(_L("GRAPHICS-EGL-0434"));
    INFO_PRINTF1(_L("CEglTest_Benchmark_CreateCloseImage::doTestStepL"));

#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
	INFO_PRINTF1(_L("CEglTest_Benchmark_CreateCloseImage can only be run with SgImage-Lite"));
#else
    TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KVG_KHR_EGL_image | KEGL_KHR_image_pixmap);
    if(!ret)
        {
        // The extension is not supported
        RecordTestResultL();
        CloseTMSGraphicsStep();
        return TestStepResult();
        }
 
    ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
    GetDisplayL();
    CreateEglSessionL();
    iEglSess->InitializeL();
    iEglSess->OpenSgDriverL();
 //----create pixmap and make context curent
    TSgImageInfo imageInfo;
    imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
    imageInfo.iPixelFormat = iPixelFormat;
    imageInfo.iSizeInPixels = iImageSize;
    //create a dummy surface and context for the purpose of enabling use of VG
    iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, CTestEglSession::EResourceCloseSgImageLate);

    //Creating regular VGImages
    //Create an array of VGImages and push them into cleanup stack
    //vgImageDeleteData takes ownership of the VGImages array. 
    //If leaving occurs or this object is destroyed from the cleanup stack 
    //it will delete all images and then the array
    VGImageFormat vgPixelFormat = EglTestConversion::PixelFormatToVgFormat(iPixelFormat);
    VGImage* vgImages = NULL;
    CVgImageDeleteData* vgImageDeleteData = new (ELeave) CVgImageDeleteData(vgImages, iNumIterations);
    CleanupStack::PushL(vgImageDeleteData);    
    vgImages = new (ELeave)VGImage[iNumIterations];
    //-------   start profiling
    iProfiler->InitResults();
    for(TInt count=iNumIterations - 1; count >= 0; --count)
        {
        //we will use VG_IMAGE_QUALITY_NONANTIALIASED flag to avoid OpenVG making the quality improvements
        //at the expense of performance (for instance to create an extra buffer) 
        vgImages[count] = vgCreateImage(vgPixelFormat, iImageSize.iWidth, iImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
        //we will check the images later, to avoid interfering with the profiler
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Creating regular VGImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
    
    //check that we created all VgImages
    for(TInt count=iNumIterations - 1; count >= 0; --count)
        {
        ASSERT_VG_TRUE(vgImages[count] !=  VG_INVALID_HANDLE);
        }    
    //Closing regular VGImage
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        vgDestroyImage(vgImages[count]);
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Closing regular VGImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   

//---  Creating VGImage from uninitialized RSgImage  
    //Create an array of SgImages and push them into cleanup stack
    //sgImageData takes ownership of the SgImages array. 
    //If leaving occurs or this object is destroyed from the cleanup stack 
    //it will delete all images and then the array
    imageInfo.iUsage = ESgUsageBitOpenVgImage;
    RSgImage* sgImages = NULL;
    CSgImageDeleteData* sgImageData = new (ELeave)CSgImageDeleteData(sgImages, iNumIterations);
    CleanupStack::PushL(sgImageData);    
    sgImages = new (ELeave) RSgImage[iNumIterations];
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        const TInt res = sgImages[count].Create(imageInfo, NULL);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
        TESTL(res == KErrNone);
#endif
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Creating uninitialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
    
    //check that we created all sgImages successfully
    for(TInt count=iNumIterations - 1; count >= 0; --count)
        {
        TESTL(!sgImages[count].IsNull());
        }    
    
    //Create an array of EglImages and push them into cleanup stack
    //eglImageDeleteData takes ownership of the EglImages array. 
    //If leaving occurs or this object is destroyed from the cleanup stack 
    //it will delete all images and then the array
    EGLImageKHR* eglImages = NULL;
    CEglImageDeleteData* eglImageDeleteData = new (ELeave)CEglImageDeleteData(*this, eglImages, iDisplay, iNumIterations); 
    CleanupStack::PushL(eglImageDeleteData);    
    eglImages = new (ELeave) EGLImageKHR[iNumIterations];
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {//we will use preserved flag as sgImage supposedly has some content
        eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[count],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Creating EGLImage from uninitialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   

    //check that we created all EglImages successfully
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)
        }
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
        iProfiler->MarkResultSetL();
        }   
    iProfiler->ResultsAnalysis(_L("Creating VGImage from EGLImage, which in turn based on uninitialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
    
    //check that we created all sgImages successfully
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
        }
    
    //Destroying VGImage/EGLImage/RSgImages
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        vgDestroyImage(vgImages[count]);
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Destroying VGImage which based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        const TBool res = iEglSess->DestroyEGLImage(iDisplay, eglImages[count]);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
        ASSERT_EGL_TRUE(res)
#endif
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Destroying EGLImage which in turn based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        sgImages[count].Close();
        iProfiler->MarkResultSetL();
        }   
    iProfiler->ResultsAnalysis(_L("Closing RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
    
    //Creating initialized VGImage from initialized RSgImage
    const TInt KDataStride = iImageSize.iWidth * EglTestConversion::BytePerPixel(iPixelFormat);
    const TInt KDataSizeInByte = KDataStride *  iImageSize.iHeight;
    TInt* data = new (ELeave) TInt[KDataSizeInByte];
    User::LeaveIfNull(data);
    CleanupStack::PushL(data);
    
    Mem::Fill(data, KDataSizeInByte / 2, 0xff);
    Mem::FillZ(data + KDataSizeInByte / 2, KDataSizeInByte / 2);
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        const TInt res = sgImages[count].Create(imageInfo, data, KDataStride);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
        TESTL(res == KErrNone);
#endif
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Creating initialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
    
    //check that we created all sgImages successfully
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        TESTL(!sgImages[count].IsNull());
        }
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {//we will use preserved flag as sgImage supposedly has some content
        eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, 
                &sgImages[count], const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Creating EGLImage from initialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    

    //check that we created all EglImages successfully
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)
        }
    
    iProfiler->InitResults();
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
        iProfiler->MarkResultSetL();
        }   
    iProfiler->ResultsAnalysis(_L("Creating VGImage from EGLImage which in turn based on initialized RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    

    //check that we created all VgImages successfully
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
        }
    
    CleanupStack::PopAndDestroy(data);    
    //Destroying VGImage/EGLImage/RSgImages
    //no need to profile as we have already done this before
    CleanupStack::PopAndDestroy(3, vgImageDeleteData);  // vgImageDeleteData, sgImageData, eglImageDeleteData  
    
    CleanAll();
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
    }

/**
@SYMTestCaseID GRAPHICS-EGL-0435

@SYMTestPriority 1

@SYMPREQ 2637

@SYMTestCaseDesc
    Performance test – Creating and destroying VGImage from an RSgImage via Open
@SYMTestActions
Environmental settings:
•   Image Size: w50 h50
•   Simulated Load: 0%
•   Pixel format ESgPixelFormatARGB_8888_PRE
•   Number of benchmark iteration: N

The method of creation of the RSgImage is similar to the case taken from GRAPHICS-EGL-RSGIMAGE_LITE-0406

From Process A:
Open the RSgDriver
Create an RSgImage
Spawn a client process B, passing in the drawable ID of the RSgImage
Wait for process B to exit

From process B:
Open RSgDriver
For i = 0 to N
    Start timer
    Open RSgImage[i]
    Stop timer and record time

    Start timer
    Create an EGLImage[i] from the RSgImage[i]
    Stop timer and record time

    Start timer
    Create a VGImage[i] from the EGLImage[i]
    Stop timer and record time

    Record total time of RSgImage[i] open and EGLImage[i] and VGImage[i] creation
End loop
Record average opening time of RSgImage, and average creation time of EGLImage, 
VGImage and the whole RSgImage-EGLImage-VGImage chain
For i = N to 0
    Start timer
    Close VGImage[i]
    Stop timer and record time

    Start timer
    Close EGLImage[i]
    Stop timer and record time

    Start timer
    Close RSgImage[i]
    Stop timer and record time

    Record total time for closing VGImage[i], EGLImage[i] and RSgImage[i]
End loop
Record average closing time of RSgImage, EGLImage, VGImage, and the whole VGImage-EGLImage-RSgImage chain

Close RSgDriver
Exit

@SYMTestExpectedResults
    The creation/opening of RSgImage, EGLImage and VGImage must return no error. 
    The average time shall be made available in an easy-to-use format 
    for further analysis and comparison. All allocated image memory should be freed
*/
TVerdict CEglTest_Benchmark_Multi_Process_CreateCloseImage::doTestStepL()
    {
    SetTestStepID(_L("GRAPHICS-EGL-0435"));
    SetTestStepName(KBenchmark_Multi_Process_CreateCloseImage);
    INFO_PRINTF1(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage::doTestStepL"));

#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
	INFO_PRINTF1(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage can only be run with SgImage-Lite"));
#else
    TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KVG_KHR_EGL_image | KEGL_KHR_image_pixmap);
    if(!ret)
        {
        // The extension is not supported
        RecordTestResultL();
        CloseTMSGraphicsStep();
        return TestStepResult();
        }

    // launch 2 processes
    Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
    
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
    }

void CEglTest_Benchmark_Multi_Process_CreateCloseImage::doProcessFunctionL(TInt aIdx)
    {
    INFO_PRINTF2(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage::doProcessFunctionL, Process %d"),aIdx);
#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    GetDisplayL();
    CreateEglSessionL(aIdx);
    iEglSess->InitializeL();    
    iEglSess->OpenSgDriverL();

    TSgImageInfo imageInfo;
    imageInfo.iUsage = ESgUsageBitOpenVgImage;
    imageInfo.iPixelFormat = iPixelFormat;
    imageInfo.iSizeInPixels = iImageSize;
    RArray<TSgDrawableId> sgIdImageList; 
    
    //Create an array of SgImages and push them into cleanup stack
    //sgImageData takes ownership of the SgImages array. 
    //If leaving occurs or this object is destroyed from the cleanup stack 
    //it will delete all images and then the array
    RSgImage* sgImages = NULL;
    CSgImageDeleteData* sgImageData = new (ELeave)CSgImageDeleteData(sgImages, iNumIterations);
    CleanupStack::PushL(sgImageData);    
    sgImages = new (ELeave) RSgImage[iNumIterations];
    
    RMsgQueue<TSgDrawableId> messageQueue;
    User::LeaveIfError(messageQueue.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
    CleanupClosePushL(messageQueue);

    //create  iNumIterations number of SgImages in one process and send them over to the second process
    INFO_PRINTF3(_L("Process %d, Start sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
    if(aIdx == 0)
        {
        for(TInt count=0; count < iNumIterations; ++count)
            {
            const TInt res = sgImages[count].Create(imageInfo, NULL);
            TESTL(res == KErrNone);
            messageQueue.SendBlocking(sgImages[count].Id());
            }
        }
    else if(aIdx == 1)
        {
        for(TInt count=0; count < iNumIterations; ++count)
            {
            TSgDrawableId sgImageId;
            messageQueue.ReceiveBlocking(sgImageId);
            sgIdImageList.AppendL(sgImageId);
            }
        }
    INFO_PRINTF3(_L("Process %d, Finish sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
    
    CleanupStack::PopAndDestroy(&messageQueue); 
    
    // Wait for both processes to reach this point
    // This is to be sure that there is no context 
    //switching whilst the profiling occurs
    Rendezvous(aIdx);
    if(aIdx == 1)
        {
        imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
        //create a dummy surface and context for the purpose of enabling use of VG
        iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, CTestEglSession::EResourceCloseSgImageLate);
        
        iProfiler->InitResults();
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            const TInt res = sgImages[count].Open(sgIdImageList[count]);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
            TESTL(res == KErrNone);
#endif            
            iProfiler->MarkResultSetL();
            }
        iProfiler->ResultsAnalysis(_L("Open RSgImage from another process"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
        
        //check that we created all sgImages successfully
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            TESTL(!sgImages[count].IsNull());
            }
        
        //Create an array of EglImages and push them into cleanup stack
        //eglImageDeleteData takes ownership of EglImages array. 
        //If leaving occurs or this object is destroyed from the cleanup stack 
        //it will delete all images and then the array
        EGLImageKHR* eglImages = NULL;
        CEglImageDeleteData* eglImageDeleteData = new (ELeave)CEglImageDeleteData(*this, eglImages, iDisplay, iNumIterations); 
        CleanupStack::PushL(eglImageDeleteData);    
        eglImages = new (ELeave) EGLImageKHR[iNumIterations];
        
        iProfiler->InitResults();
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {//we will use preserved flag as sgImage supposedly has some content
            eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[count],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
            iProfiler->MarkResultSetL();
            }
        iProfiler->ResultsAnalysis(_L("Creating EGLImage from RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
        
        //check that we created all EglImages successfully
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)
            }
        
        //Create an array of VGImages and push them into cleanup stack
        //vgImageDeleteData takes ownership of VgImages array. 
        //If leaving occurs or this object is destroyed from the cleanup stack 
        //it will delete all images and then the array
        VGImage* vgImages = NULL;
        CVgImageDeleteData* vgImageDeleteData = new (ELeave) CVgImageDeleteData(vgImages, iNumIterations);
        CleanupStack::PushL(vgImageDeleteData);
        vgImages = new (ELeave) VGImage[iNumIterations];
        
        iProfiler->InitResults();
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
            iProfiler->MarkResultSetL();
            }   
        iProfiler->ResultsAnalysis(_L("Creating VGImage from EGLImage, which in turn based on SgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   

        //check that we created all VgImages successfully
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
            }   
        
        sgIdImageList.Reset();
        
        //Destroying VGImage/EglImage/RSgImages
        iProfiler->InitResults();
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            vgDestroyImage(vgImages[count]);
            iProfiler->MarkResultSetL();
            }
        iProfiler->ResultsAnalysis(_L("Destroying VGImage based on EGLImage which in turn based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
        
        iProfiler->InitResults();
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            const TBool res = iEglSess->DestroyEGLImage(iDisplay, eglImages[count]);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
            ASSERT_EGL_TRUE(res);
#endif            
            iProfiler->MarkResultSetL();
            }
        iProfiler->ResultsAnalysis(_L("Destroying EGLImage which based on RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
        
        iProfiler->InitResults();
        for(TInt count=iNumIterations-1; count >= 0; --count)
            {
            sgImages[count].Close();
            iProfiler->MarkResultSetL();
            }   
        iProfiler->ResultsAnalysis(_L("Closing RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);    
        CleanupStack::PopAndDestroy(2, eglImageDeleteData); //eglImageDeleteData, vgImageDeleteData     
        }

    // Wait for both processes to reach this point
    Rendezvous(aIdx);
    CleanupStack::PopAndDestroy(sgImageData);
    CleanAll();
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    }


/**
@SYMTestCaseID GRAPHICS-EGL-0436

@SYMTestPriority 1

@SYMPREQ 2637

@SYMTestCaseDesc
    Performance test - Drawing of VGImage

@SYMTestPurpose             
Compare the relative speed of drawing a regular pre-existing VGImage with the 
speed of mapping in a VGImage (starting with a drawable id) and then drawing that.

@SYMTestActions
Environmental settings:
•   Image Size: w50 h50
•   Simulated Load: 0%
•   Pixel format ESgPixelFormatARGB_8888_PRE
•   Number of benchmark iteration: N (may vary depending on hardware capacity)

From the main test process:
Spawn two processes A and B
From process A:
Open RSgDriver
Construct TSgImageInfo object with
•   Size: 50x50
•   PixelFormat: ESgPixelFormatARGB_8888_PRE
•   Usage: ESgUsageBitOpenVgImage;

Creation of the RSgImages:
For i = 0 to N
      Form pixel data in such way that there will be a mixture of opaque and transparent pixels.     
      At least one coordinate of the opaque pixel will be unique for any iteration.
      Creating RSgImage with initialized data, size: 50x50 and format:  VG_sARGB_8888_PRE. 
      Send RSgImage drawableID to process B
End loop
Close all RSgImages after they will have been opened in process B
Close RSgDriver after process B finishes with benchmark measurement.

From process B:

For i = 0 to N
     Receive and store drawableID[i] from process A
End loop

Init EGL, create context and pixmap surface. Make the surface current.
Creating regular VGImage:
For i = 0 to N
    Create VGImage[i] with size: 50x50 and format:  VG_sARGB_8888_PRE
    SetSubData for VGImage[i] with the same data which were supplied on RSgImage creation
End loop

Draw regular VGImage:
For j = 0 to 4
    Start timer
    For i = N to 0
        Draw VGImage[i]
    End loop i
    Stop timer and record time
End loop j
Complete all outstanding requests on the current context (vgFinish)
Record max, min, average drawing time of VGImage
Check that deviation between max and min time doesn’t exceed 5% (max – min / mean) < 0.05

Destroy all regular VGImages

Open RSgDriver
Mapping in VGImage from initialized RSgImage and perform drawing:
For j = 0 to 4
    Start timer
    For i = N to 0
        Open RSgImage[i] with drawableID[i]
        Create an EGLImage[i] from the RSgImage[i]
        Create a VGImage[i] from the EGLImage[i]
        Draw VGImage[i]
    End loop i
    Complete all outstanding requests on the current context (vgFinish)
    Stop timer and record time
End loop j
Record max, min, average mapping and drawing time of VGImage
Check that deviation between max and min time doesn’t exceed 5% (max – min / mean) < 0.05

Destroy context, surface
Close all VGImages, EGLImages and RSgImages
Terminate Egl environment
Close RSgDriver

@SYMTestExpectedResults
The creation of RSgImage, EGLImage and VGImage must return no error. 
The drawing speed of regular VGImage and mapping VGImage (starting from drawable id) 
with following draw is made available in an easy-to-use format for further analysis and 
comparison.
*/
TVerdict CEglTest_Benchmark_DrawImage::doTestStepL()
    {
    SetTestStepID(_L("GRAPHICS-EGL-0436"));
    SetTestStepName(KBenchmark_DrawImage);
    INFO_PRINTF1(_L("CEglTest_Benchmark_DrawImage::doTestStepL"));

#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    INFO_PRINTF1(_L("CEglTest_Benchmark_DrawImage can only be run with SgImage-Lite"));
#else
    TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KVG_KHR_EGL_image | KEGL_KHR_image_pixmap);
    if(ret)
        {
        // launch 2 processes
        Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
        }
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE

    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
    }

void CEglTest_Benchmark_DrawImage::doProcessFunctionL(TInt aIdx)
    {
#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    GetDisplayL();
    CreateEglSessionL(aIdx);
    iEglSess->InitializeL();    
    iEglSess->OpenSgDriverL();

    TSgImageInfo imageInfo;
    imageInfo.iUsage = ESgUsageBitOpenVgImage;
    imageInfo.iPixelFormat = iPixelFormat;
    imageInfo.iSizeInPixels = iImageSize;
    RArray<TSgDrawableId> sgIdImageList; 
    
    const TInt KNumAttempt = 5;
    const TInt KNumImagesToDraw = iNumIterations;
    //Create an array of SgImages and push them into cleanup stack
    //sgImageData takes ownership of the SgImages array. 
    //If leaving occurs or this object is destroyed from the cleanup stack 
    //it will delete all images and then the array
    RSgImage* sgImages = NULL;
    CSgImageDeleteData* sgImageData = new (ELeave)CSgImageDeleteData(sgImages, KNumImagesToDraw);
    CleanupStack::PushL(sgImageData);    
    sgImages = new (ELeave) RSgImage[KNumImagesToDraw];
    
    // the message queue will be used to pass image IDs across process boundary
    RMsgQueue<TSgDrawableId> messageQueue;
    User::LeaveIfError(messageQueue.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
    CleanupClosePushL(messageQueue);

    //create  iNumIterations * KNumAttempt number of SgImages in one process and send them over to the second process
    INFO_PRINTF3(_L("Process %d, Start sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
    if(aIdx == 0)
        {
        TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
        for(TInt index=0; index < KNumImagesToDraw; ++index)
            {
            CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, iImageSize, index);
            CleanupStack::PushL(bitmap);
            ASSERT_EQUALS(sgImages[index].Create(imageInfo, bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
            messageQueue.SendBlocking(sgImages[index].Id());
            CleanupStack::PopAndDestroy(bitmap);
            }
        }
    else if(aIdx == 1)
        {
        for(TInt index=0; index < KNumImagesToDraw; ++index)
            {
            TSgDrawableId sgImageId;
            messageQueue.ReceiveBlocking(sgImageId);
            sgIdImageList.AppendL(sgImageId);
            }
        }
    CleanupStack::PopAndDestroy(&messageQueue);
    INFO_PRINTF3(_L("Process %d, Finish sending %d SgImage IDs to other process..."), aIdx, iNumIterations);
    //We expect to reach this point from both processes simultaneously 
    //this is because ReceiveBlocking/SendBlocking are synchronous
    
    if(aIdx == 1)
        {
        imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
        //create a dummy surface and context for the purpose of enabling use of VG
        iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, CTestEglSession::EResourceCloseSgImageLate);

        //Creating regular VGImages
        //Create an array of VGImages and push them into cleanup stack
        //vgImageDeleteData takes ownership of the VGImages array. 
        //If leaving occurs or this object is destroyed from the cleanup stack 
        //it will delete all images and then the array
        VGImageFormat vgPixelFormat = EglTestConversion::PixelFormatToVgFormat(iPixelFormat);
        VGImage* vgImages = NULL;
        CVgImageDeleteData* vgImageDeleteData = new (ELeave) CVgImageDeleteData(vgImages, KNumImagesToDraw);
        CleanupStack::PushL(vgImageDeleteData);    
        vgImages = new (ELeave)VGImage[KNumImagesToDraw];
        for(TInt index=KNumImagesToDraw - 1; index >= 0; --index)
            {
            //we will use VG_IMAGE_QUALITY_NONANTIALIASED flag to avoid OpenVG making the quality improvements
            //at the expense of performance (for instance to create an extra buffer) 
            vgImages[index] = vgCreateImage(vgPixelFormat, iImageSize.iWidth, iImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
            ASSERT_VG_TRUE(vgImages[index] !=  VG_INVALID_HANDLE);
            
            TDisplayMode bitmapMode = EglTestConversion::VgFormatToDisplayMode(EglTestConversion::PixelFormatToVgFormat(iPixelFormat));
            CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, iImageSize, index);
            CleanupStack::PushL(bitmap);
            // Add pixel data to the VGImage reference from the bitmap reference. 
            // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
            TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
            TInt stride = bitmap->DataStride();
            address += (iImageSize.iHeight - 1) * stride;
            vgImageSubData(vgImages[index], address, -stride, 
                    KDefaultSurfaceFormat, 0,0, iImageSize.iWidth, iImageSize.iHeight);
            ASSERT_VG_ERROR(VG_NO_ERROR);
            CleanupStack::PopAndDestroy(bitmap);
            }
#ifdef ENABLE_BENCHMARK_VERBOSE_LOGGING
        iProfiler->SetStoreResultInTimingOrder(ETrue);
#endif        
        //--------- start profiling
        INFO_PRINTF1(_L("Profiling of drawing of the regular VG image"));
        iProfiler->InitResults();
        for(TInt count = KNumAttempt - 1; count >= 0; --count)
            {
            for(TInt index=iNumIterations - 1; index >= 0; --index)
                {
                vgDrawImage(vgImages[index]);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
                ASSERT_VG_ERROR(VG_NO_ERROR);
#endif            
                }
            vgFinish();
#ifdef ENABLE_CHECKING_WHILST_PROFILING
            ASSERT_VG_ERROR(VG_NO_ERROR);
#endif            
            iProfiler->MarkResultSetL();
            }
        iProfiler->ResultsAnalysis(_L("Drawing of the regular VGImages"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), KNumAttempt);   
#ifdef ENABLE_BENCHMARK_VERBOSE_LOGGING
        iProfiler->ShowResultArrayInTimingOrder();
        
        const TInt KDeviationRegular = ((((TReal)(iProfiler->TimeMax())) - iProfiler->TimeMin()) / (TReal)(iProfiler->Mean())) * 100;
        INFO_PRINTF3(_L("Deviation in percentage between min and max number of images drawing ((TimeMax - TimeMin) / Mean * 100): %d, threshold: %d "), KDeviationRegular, KBenchmarkDrawImageThreshold);
        if(KDeviationRegular > KBenchmarkDrawImageThreshold)
            {
            //unfortunatelly EGL test framework currently ignores the error because this is a spawned process, and not 
            // the main cteststep process. We could leave, but that would be too harsh in this situation
            WARN_PRINTF1(_L("***The deviation has exceeded threshold, the number of iteration needs to be increased!!!"));
            }
#endif        
        //--------- stop profiling
        
        //destroy vgImages
        for(TInt index=0; index < KNumImagesToDraw; index++)
            {
            vgDestroyImage(vgImages[index]);
            vgImages[index]=VG_INVALID_HANDLE;
            ASSERT_VG_ERROR(VG_NO_ERROR);
            }
        
        //Create an array of EglImages and push them into cleanup stack
        //eglImageDeleteData takes ownership of the EglImages array. 
        //If leaving occurs or this object is destroyed from the cleanup stack 
        //it will delete all images and then the array
        EGLImageKHR* eglImages = NULL;
        CEglImageDeleteData* eglImageDeleteData = new (ELeave)CEglImageDeleteData(*this, eglImages, iDisplay, KNumImagesToDraw); 
        CleanupStack::PushL(eglImageDeleteData);    
        eglImages = new (ELeave) EGLImageKHR[KNumImagesToDraw];
        
        //---------------start profiling
        INFO_PRINTF1(_L("Profiling of mapping in and drawing of the VG images with underlying RSgImage"));
        iProfiler->InitResults();
        for(TInt count = KNumAttempt - 1; count >= 0; --count)
            {//we will run KNumAttemt times in a row and check that the set of results is consistent, 
            // i.e. deviation between max and min time doesn't exceed KBenchmarkDrawImageThreshold percentage
         
            for(TInt index=iNumIterations - 1; index >= 0; --index)
                {
#ifdef ENABLE_CHECKING_WHILST_PROFILING
                const TInt res = sgImages[index].Open(sgIdImageList[index]);
                TESTL(res == KErrNone);
                TESTL(!sgImages[index].IsNull());
                eglImages[index]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[index],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
                ASSERT_EGL_TRUE(eglImages[index] != EGL_NO_IMAGE_KHR)
                vgImages[index] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[index]);
                ASSERT_VG_TRUE(vgImages[index] != VG_INVALID_HANDLE);
                vgDrawImage(vgImages[index]);
                ASSERT_VG_ERROR(VG_NO_ERROR);
#else                
                const TInt res = sgImages[index].Open(sgIdImageList[index]);
                eglImages[index]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[index],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
                vgImages[index] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[index]);
                vgDrawImage(vgImages[index]);
                
#endif //ENABLE_CHECKING_WHILST_PROFILING
                }
            vgFinish();
#ifdef ENABLE_CHECKING_WHILST_PROFILING
            ASSERT_VG_ERROR(VG_NO_ERROR);
#endif            
            iProfiler->MarkResultSetAndSuspendL(); //mark the end of the iteration. The timer will not be resumed yet 
            
            // Clean Sg/Vg/Egl images. 
            // This is to ensure that expanding of the images will not impact measurement
            for(TInt index=iNumIterations - 1; index >= 0; --index)
                {
                sgImages[index].Close();
                vgDestroyImage(vgImages[index]);
                vgImages[index] = VG_INVALID_HANDLE;
                iEglSess->DestroyEGLImage( iDisplay, eglImages[index]);
                eglImages[index] = EGL_NO_IMAGE_KHR;
                }
            
            iProfiler->StartTimer();
            }
        //----------------stop profiling

        const TInt KDeviation = ((((TReal)(iProfiler->TimeMax())) - iProfiler->TimeMin()) / (TReal)(iProfiler->Mean())) * 100;
        INFO_PRINTF3(_L("Deviation in percentage between min and max number of images drawing ((TimeMax - TimeMin) / Mean * 100): %d, threshold: %d "), KDeviation, KBenchmarkDrawImageThreshold);
        if(KDeviation > KBenchmarkDrawImageThreshold)
            {
			//unfortunatelly EGL test framework currently ignores the error because this is a spawned process, and not 
			// the main cteststep process. We could leave, but that would be too harsh in this situation
			WARN_PRINTF1(_L("***The deviation has exceeded threshold, the number of iteration needs to be increased!!!"));
            }
        
        iProfiler->ResultsAnalysis(_L("Drawing VGImages with underlying RSgImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), KNumAttempt);
#ifdef ENABLE_BENCHMARK_VERBOSE_LOGGING
        iProfiler->ShowResultArrayInTimingOrder();
#endif        
        sgIdImageList.Reset();
        }
    
    //Introduce synchronization point here to make sure that RSgImages are not closed from the 
    //first process while the second one is busy with benchmark measurement
    Rendezvous(aIdx);
    if(aIdx == 0)
        {
        //Destroying VGImage/EGLImage/RSgImages
        //no need to profile as we have already done this before
        CleanupStack::PopAndDestroy(sgImageData);  // sgImageData  
        }
    else
        {
        //Destroying VGImage/EGLImage/RSgImages
        //no need to profile as we have already done this before
        CleanupStack::PopAndDestroy(3, sgImageData);  // sgImageData, vgImageDeleteData, eglImageDeleteData
        }
    CleanAll();
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    }