egl/egltest/src/egltest_benchmark_sgimage.cpp
author Jose Thachil<jose.thachil@cell-telecom.com>
Wed, 12 May 2010 13:05:33 +0100
branchEGL_MERGE
changeset 59 0fb7b31791c3
parent 0 5d03bc08d59c
child 26 15986eb6c500
permissions -rw-r--r--
Minor updates.

// 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");

//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"));
	RecordTestResultL();
	CloseTMSGraphicsStep();
	return TestStepResult();
#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();
    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    }

/**
@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"));
	RecordTestResultL();
	CloseTMSGraphicsStep();
	return TestStepResult();
#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());
    
    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    }

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 VGImage
@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)

Creating regular VGImage
Init EGL, create context and surface
For i = 0 to N
    Create VGImage[i] with size: 50x50 and format:  VG_sARGB_8888_PRE
    SetSubData for VGImage[i] 
End loop

Draw VGImage
For i = N to 0
    Start timer
    Draw VGImage[i]
    Stop timer and record time
End loop
Record average time of drawing VGImage

Closing regular VGImage
For i = N to 0
    Destroy VGImage[i]
End loop

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

For i = N to 0
    Create RSgImage[i] with arguments TSgImageInfo with initialized data which were supplied to regular VGImage 
    Create an EGLImage[i] from the RSgImage[i]
    Create a VGImage[i] from the EGLImage[i]
End loop

Draw VGImage which is based on RSgImage
For i = N to 0
    Start timer
    Draw VGImage[i]
    Stop timer and record time
End loop
Record average time of drawing VGImage

Close all VGImages, EGLImages and RSgImages
Close RSgDriver

@SYMTestExpectedResults
The creation of RSgImage, EGLImage and VGImage must return no error. 
The average drawing time of regular VGImage and VGImage with underlying RSgImage is 
made available in an easy-to-use format for further analysis and comparison.
*/
TVerdict CEglTest_Benchmark_DrawImage::doTestStepL()
    {
    SetTestStepID(_L("GRAPHICS-EGL-0436"));
    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"));
    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
#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);

    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);

    //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];
    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);
        ASSERT_VG_TRUE(vgImages[count] !=  VG_INVALID_HANDLE);
        
        vgImageSubData(vgImages[count],
                data, KDataStride,
                vgPixelFormat,
                0, 0, iImageSize.iWidth, iImageSize.iHeight);
        ASSERT_VG_ERROR(VG_NO_ERROR);
        }
    
    //--------- start profiling
    iProfiler->InitResults();
    for(TInt count=iNumIterations - 1; count >= 0; --count)
        {
        vgDrawImage(vgImages[count]);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
        ASSERT_VG_ERROR(VG_NO_ERROR);
#endif            
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Drawing regular VGImage"), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
    //--------- stop profiling
    
    //destroy vgImages
    for(TInt count=iNumIterations - 1; count >= 0; --count)
        {
        vgDestroyImage(vgImages[count]);
        ASSERT_VG_ERROR(VG_NO_ERROR);
        vgImages[count]=VG_INVALID_HANDLE;
        }
    
    //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];
    
    //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];
    
    //Creating VGImage from initialized RSgImage
    for(TInt count=iNumIterations-1; count >= 0; --count)
        {
        const TInt res = sgImages[count].Create(imageInfo, data, KDataStride);
        TESTL(res == KErrNone);
        TESTL(!sgImages[count].IsNull());

        eglImages[count]= iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImages[count],const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
        ASSERT_EGL_TRUE(eglImages[count] != EGL_NO_IMAGE_KHR)

        vgImages[count] = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages[count]);
        ASSERT_VG_TRUE(vgImages[count] != VG_INVALID_HANDLE);
        }
    
    //---------------start profiling
    iProfiler->InitResults();
    for(TInt count=iNumIterations - 1; count >= 0; --count)
        {
        vgDrawImage(vgImages[count]);
#ifdef ENABLE_CHECKING_WHILST_PROFILING
        ASSERT_VG_ERROR(VG_NO_ERROR);
#endif            
        iProfiler->MarkResultSetL();
        }
    iProfiler->ResultsAnalysis(_L("Drawing VGImage with underlying RSgImage "), 0, EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), EglTestConversion::PixelFormatToDisplayMode(iPixelFormat), iNumIterations);   
    //----------------stop profiling
    
    //Destroying VGImage/EGLImage/RSgImages
    //no need to profile as we have already done this before
    CleanupStack::PopAndDestroy(4, data);  // data, vgImageDeleteData, sgImageData, eglImageDeleteData  
    
    CleanAll();
    RecordTestResultL();
    CloseTMSGraphicsStep();
    return TestStepResult();
#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    }