--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/egl/egltest/src/egltest_oom_sgimage.cpp Tue Aug 31 16:31:06 2010 +0300
@@ -0,0 +1,1335 @@
+// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @test
+*/
+
+#include <test/tefunit.h> // for ASSERT macros
+#include <e32msgqueue.h>
+
+#include <test/egltestcommonprocess.h>
+#include <test/egltestcommonconversion.h>
+#include <test/egltestcommoninisettings.h>
+#include "egltest_oom_sgimage.h"
+
+
+_LIT(KOOMSection, "OOM");
+
+
+//Since we want to exhaust the memory it probably makes sense to use any 32bpp mode
+//There is no need to put it into INI file
+const TUidPixelFormat KOOMPixelFormat = EUidPixelFormatARGB_8888;
+
+// Deviation in per cent for test 0442 and 0443
+const TInt KOOMSgImageDeviation = 5;
+
+
+CEglTest_OOM_Base::~CEglTest_OOM_Base()
+ {
+ CleanGraphicsResources();
+ CleanAll();
+ }
+
+TVerdict CEglTest_OOM_Base::doTestStepPreambleL()
+ {
+ TVerdict verdict = CEglTestStep::doTestStepPreambleL();
+ //read all parameters from config
+ CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
+ CleanupStack::PushL(iniParser);
+ iNumIterations = iniParser->GetNumberOfIterations(KOOMSection);
+ 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(KOOMSection);
+ 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 = KOOMPixelFormat;
+
+ iThresholdGPUUsedMemory = iniParser->GetThresholdGPUUsedMemory(KOOMSection);
+ if(iThresholdGPUUsedMemory == 0)
+ {
+ ERR_PRINTF1(_L("Threshold GPU used memory whether is not specified in INI file or is 0, the test will not be executed!"));
+ User::Leave(KErrArgument);
+ }
+
+ iThresholdLastIteration = iniParser->GetThresholdLastIteration(KOOMSection);
+ if(iThresholdLastIteration == 0)
+ {
+ ERR_PRINTF1(_L("Threshold last iteration whether is not specified in INI file or is 0, the test will not be executed!"));
+ User::Leave(KErrArgument);
+ }
+
+ CleanupStack::PopAndDestroy(iniParser);
+
+ INFO_PRINTF4(_L("**** The test will be run in following configuration: number of iterations %d, image size (%d, %d)"), iNumIterations, iImageSize.iWidth, iImageSize.iHeight);
+ INFO_PRINTF3(_L("**** Threshold GPU used memory %d, threshold last iteration %d"), iThresholdGPUUsedMemory, iThresholdLastIteration);
+
+ PrintUsedPixelConfiguration();
+ return verdict;
+ }
+
+TVerdict CEglTest_OOM_Base::doTestStepPostambleL()
+ {
+ //to keep heap checking happy we have to clean up before destructor
+ CleanGraphicsResources();
+ return CEglTestStep::doTestStepPostambleL();
+ }
+
+//receive last successful index from the client process
+void CEglTest_OOM_Base::ReceiveMessageFromClient(RMsgQueue<TEglStepMessageBuffer>& aMessageQueueClientProcParam)
+ {
+ TEglStepMessageBuffer param;
+ aMessageQueueClientProcParam.ReceiveBlocking(param);
+ iLastIterationNumber = *(TInt*) (param.iBuf);
+ }
+
+//send last successful index to the main process for analysis
+void CEglTest_OOM_Base::SendIndexToMainProcessL(TInt aIndex)
+ {
+ TEglStepMessageBuffer param;
+ RMsgQueue<TEglStepMessageBuffer> messageQueueClientProcParam;
+ CleanupClosePushL(messageQueueClientProcParam);
+ User::LeaveIfError(messageQueueClientProcParam.Open(EProcSlotCustomClientParam, EOwnerProcess));
+ *((TInt*)param.iBuf) = aIndex;
+ messageQueueClientProcParam.SendBlocking(param);
+ CleanupStack::PopAndDestroy(&messageQueueClientProcParam);
+ }
+
+//clean Sg/Egl/Vg images allocated. Reset arrays for various deviation variables.
+void CEglTest_OOM_Base::CleanGraphicsResources()
+ {
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ while(iSurfaces.Count() > 0)
+ {
+ eglDestroySurface(iDisplay, iSurfaces[0]);
+ iSurfaces.Remove(0);
+ }
+ iSurfaces.Reset();
+
+ while(iVgImages.Count() > 0)
+ {
+ vgDestroyImage(iVgImages[0]);
+ iVgImages.Remove(0);
+ }
+ iVgImages.Reset();
+
+ while(iEglImages.Count() > 0)
+ {
+ iEglSess->DestroyEGLImage(iDisplay, iEglImages[0]);
+ iEglImages.Remove(0);
+ }
+ iEglImages.Reset();
+
+ while(iSgImages.Count() > 0)
+ {
+ iSgImages[0].Close();
+ iSgImages.Remove(0);
+ }
+ iSgImages.Reset();
+
+ iGPUUsedMemory.Reset();
+ iLastIterations.Reset();
+#endif
+ }
+
+//if an array is empty, it returns zero for both aMin and aMax
+void CEglTest_OOM_Base::GetMinMax(const RArray<TInt>& aArray, TInt& aMin, TInt& aMax) const
+ {
+ aMin = 0;
+ aMax = 0;
+ if(aArray.Count() == 0)
+ return;
+ aMax = aArray[0];
+ aMin = aArray[0];
+ for(TInt ii = 1; ii < aArray.Count(); ii++)
+ {
+ if(aMin > aArray[ii])
+ {
+ aMin = aArray[ii];
+ }
+ if(aMax < aArray[ii])
+ {
+ aMax = aArray[ii];
+ }
+ }
+ }
+
+TInt CEglTest_OOM_Base::Deviation(const RArray<TInt>& aArray) const
+ {
+ TInt min = 0;
+ TInt max = 0;
+
+ GetMinMax(aArray, min, max);
+ if(max == 0)
+ return 0; // to avoid division by zero
+ return (max - min) / (((TReal)(min + max)) / 2) * 100;
+ }
+
+//Calculate and output deviation of various parameters.
+//If the measurement for particular parameter doesnt take place, for instance,
+//due to absence of the extension, the output will be skipped.
+void CEglTest_OOM_Base::CheckDeviation()
+ {
+ TInt res = KErrNone;
+
+ if(iGPUUsedMemory.Count() > 0)
+ {
+ res = Deviation(iGPUUsedMemory);
+ ASSERT_TRUE(iThresholdGPUUsedMemory >= res);
+ INFO_PRINTF3(_L("GPU used memory deviation %d %%, threshold %d %%"), res, iThresholdGPUUsedMemory);
+ }
+
+ if(iLastIterations.Count() > 0)
+ {
+ res = Deviation(iLastIterations);
+ ASSERT_TRUE(iThresholdLastIteration >= res);
+ INFO_PRINTF3(_L("Last iteration deviation %d %%, threshold %d %%"), res, iThresholdLastIteration);
+ }
+ }
+
+void CEglTest_OOM_Base::RetrieveExtensionDataL()
+ {
+ PrintEglResourceProfilingInfoL();
+ INFO_PRINTF2(_L("Nember iterations before the failure occurs, %d"), iLastIterationNumber);
+ iLastIterations.Append(iLastIterationNumber);
+ iLastIterationNumber = -1;
+ }
+
+//Print GPU information provided be NOK_resource_profiling2 egl extension
+//Some data, like GPU usage, will be memorized for further comparison
+//This extension is optional and may not be present in the system
+void CEglTest_OOM_Base::PrintEglResourceProfilingInfoL()
+ {
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+#ifdef EGL_PROF_MEMORY_USAGE_THRESHOLD_NOK
+
+ GetDisplayL();
+ CreateEglSessionL();
+ iEglSess->InitializeL();
+
+ if(!iPFnEglQueryProfilingDataNOK)
+ {
+ iPFnEglQueryProfilingDataNOK = (PFNEGLQUERYPROFILINGDATANOKPROC) eglGetProcAddress("eglQueryProfilingDataNOK");
+
+ if(!iPFnEglQueryProfilingDataNOK)
+ {
+ CleanAll();
+ WARN_PRINTF1(_L("NOK_resource_profiling2 extension is not available"));
+ return;
+ }
+ }
+
+ EGLint data_count;
+ // Find out how much profiling data is available
+ iPFnEglQueryProfilingDataNOK(iDisplay,
+ EGL_PROF_QUERY_GLOBAL_BIT_NOK |
+ EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
+ NULL,
+ 0,
+ &data_count);
+
+ // Allocate room for the profiling data
+ EGLint* prof_data = (EGLint*)User::AllocL(data_count * sizeof(EGLint));
+
+ CleanupStack::PushL(prof_data);
+
+ // Retrieve the profiling data
+ iPFnEglQueryProfilingDataNOK(iDisplay,
+ EGL_PROF_QUERY_GLOBAL_BIT_NOK |
+ EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
+ prof_data,
+ data_count,
+ &data_count);
+
+ // Iterate over the returned data
+ EGLint i = 0;
+ while (i < data_count)
+ {
+ switch (prof_data[i++])
+ {
+ case EGL_PROF_TOTAL_MEMORY_NOK:
+ INFO_PRINTF2(_L("Total memory: %d"), prof_data[i++]);
+ break;
+ case EGL_PROF_USED_MEMORY_NOK:
+ iGPUUsedMemory.AppendL(prof_data[i]);
+ INFO_PRINTF2(_L("Used memory: %d"), prof_data[i++]);
+ break;
+ case EGL_PROF_PROCESS_ID_NOK:
+ if(sizeof(EGLNativeProcessIdTypeNOK) == 4)
+ {
+ INFO_PRINTF2(_L("Process ID(4 bytes), 0x%08X"), prof_data[i++]);
+ }
+ else if(sizeof(EGLNativeProcessIdTypeNOK) == 8)
+ {
+ EGLNativeProcessIdTypeNOK processId = ((EGLNativeProcessIdTypeNOK)(prof_data[i])) + (((EGLNativeProcessIdTypeNOK)(prof_data[i + 1]))<<32);
+ RProcess process;
+ TProcessId pid(processId);
+ TInt err = process.Open(pid);
+ if (err == KErrNone)
+ {
+ TPtrC ptr(process.FullName());
+ INFO_PRINTF4(_L("Process ID, %lu - 0x%lu - %S"), processId, processId, &ptr);
+ process.Close();
+ }
+ else
+ {//this parameter is not in use in the test, thus is no point to set an error.
+ WARN_PRINTF4(_L("Process ID, %lu - 0x%lx, fail to open process with error %d"), processId, processId, err);
+ }
+ i += 2;
+ }
+ else
+ {//this parameter is for information only. It doesn't impact our measurement. So there is no need to set an error.
+ WARN_PRINTF1(_L("Unknown EGLNativeProcessIdTypeNOK"));
+ }
+ break;
+ case EGL_PROF_PROCESS_USED_PRIVATE_MEMORY_NOK:
+ INFO_PRINTF2(_L("Process used private memory: %d"), prof_data[i++]);
+ break;
+ case EGL_PROF_PROCESS_USED_SHARED_MEMORY_NOK:
+ INFO_PRINTF2(_L("Process used shared memory: %d"), prof_data[i++]);
+ break;
+ }
+ }
+
+ // Free allocated memory
+ CleanupStack::PopAndDestroy(prof_data);
+ CleanAll();
+
+#endif //EGL_PROF_MEMORY_USAGE_THRESHOLD_NOK
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-EGL-0438
+
+@SYMTestPriority 1
+
+@SYMPREQ 2637
+
+@SYMTestCaseDesc
+ OOM test Free VG/Egl/Sg Images while the process which owns them is terminated
+
+@SYMTestActions
+Environmental settings:
+ Image Size: w50 h50
+ List of simulated load: 0%
+ List of pixel formats
+ESgPixelFormatARGB_8888
+ Client process priorities - all the same
+ Client process random parameters:
+- None
+
+The creation of RSgImages and launching of processes is along the lines of the method outlined in GRAPHICS-EGL-RSGIMAGE_LITE-0406
+
+ From the main process:
+ For i = 0 to N
+ Spawn 2 client processes A and B.
+ Signal all client processes to start by use of a semaphore
+ Wait until client processes exit
+ If the test fails not due to the memory allocation record an error code to the log file then set a test result as a failure and skip further actions.
+ End loop
+ Exit
+
+ From client process A:
+ Get EGL display
+ Initialize EGL
+ Open RSgDriver
+ Create context, pbuffer surface.
+ Make pbuffer surface current for the given context
+ Loop until exit condition met
+ Start loop:
+Create SgImage
+Create EglImage with underlying SgImage
+ Create VgImage with underlying EglImage
+ Exit condition Sg/Egl/Vg image creation has failed.
+End loop:
+ Destroy the pbuffer surface
+Log the last iteration number and exact operation which precedes a failure.
+In the environment supporting NOK_resource_profiling2 extension retrieve for further analyzes the following GPU profiling data (if available):
+ Total memory
+ Used memory
+ Process ID
+ Process used private memory
+ Process used shared memory
+
+Make the process busy by putting it into the indefinite loop.
+
+ From client process B:
+ Wait until process A fails with the image creation.
+ Terminate the process A.
+
+@SYMTestExpectedResults
+For each step from 0 to N in the main process,
+- Image allocation failure must happen at approximately the same iteration in process A.
+ MaxIterationNumber MinIterationNumber < Threashold, where Treashold will not
+ exceeds 5 and exact value to be defined during implementation.
+- GPU memory usage retrieved through NOK_resource_profiling2 extension, if available,
+ is consistent and doesnt decrease over the time.
+ MaxGPUMemoryUsage MinGPUMemoryUsage < Threshold, where Threshold will not exceed
+ 5 and exact value to be defined during implementation.
+*/
+TVerdict CEglTest_OOM_CloseVGImageWithTermination::doTestStepL()
+ {
+ SetTestStepID(_L("GRAPHICS-EGL-0438"));
+ SetTestStepName(KOOM_CloseVGImageWithTermination);
+ INFO_PRINTF1(_L("CEglTest_Benchmark_Multi_Process_CreateCloseImage::doTestStepL"));
+
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseVGImageWithTermination 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 supported
+ // if the test fails not due to the memory allocation, then skip further actions
+ for(TInt index = 0; (index < iNumIterations) && (TestStepResult()== EPass); index++)
+ {
+ // launch 2 processes
+ Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
+ RetrieveExtensionDataL();
+ }
+ CheckDeviation();
+ }
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ RecordTestResultL();
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+void CEglTest_OOM_CloseVGImageWithTermination::doProcessFunctionL(TInt aIdx)
+ {
+ INFO_PRINTF2(_L("CEglTest_OOM_CloseVGImageWithTermination::doProcessFunctionL, Process %d"),aIdx);
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ if(aIdx == 0)
+ {
+ GetDisplayL();
+ CreateEglSessionL(aIdx);
+ iEglSess->InitializeL();
+ iEglSess->OpenSgDriverL();
+
+ //create a dummy surface and context for the purpose of enabling use of VG
+ TEglTestConfig pbufferFormat = EglTestConversion::VgFormatToPBufferSurfaceFormat(EglTestConversion::PixelFormatToVgFormat(iPixelFormat));
+ EGLConfig currentConfig = 0;
+ TRAPD(res, currentConfig = iEglSess->GetConfigExactMatchL( pbufferFormat ));
+ User::LeaveIfError(res);
+
+ iEglSess->CreatePbufferSurfaceAndMakeCurrentL(currentConfig, iImageSize, EGL_OPENVG_API);
+ TInt index = 0;
+ TSgImageInfo imageInfo;
+ imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
+ imageInfo.iPixelFormat = iPixelFormat;
+ imageInfo.iSizeInPixels = iImageSize;
+ for(;;++index)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(imageInfo, NULL);
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected %d or %d"), index, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ EGLImageKHR eglImages = iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImage,const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
+ EGLint eglError = eglGetError();
+ if((eglImages == EGL_NO_IMAGE_KHR) || (eglError != EGL_SUCCESS))
+ {
+ INFO_PRINTF4(_L("***Fail to create EGLImage after %d attempts, error: %d, expected: %d"), index, eglError, EGL_BAD_ALLOC);
+ ASSERT_TRUE(eglError == EGL_BAD_ALLOC);
+ break;
+ }
+
+ VGImage vgImage = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImages);
+ VGErrorCode vgError = vgGetError();
+ if(vgImage == VG_INVALID_HANDLE || (vgError != VG_NO_ERROR))
+ {
+ INFO_PRINTF4(_L("***Fail to create VGImage after %d attempts, error: %d, expected: %d"), index, vgError, VG_OUT_OF_MEMORY_ERROR);
+ ASSERT_TRUE(vgError == VG_OUT_OF_MEMORY_ERROR);
+ break;
+ }
+ } //for
+ SendIndexToMainProcessL(index);
+ }
+ Rendezvous(aIdx);
+
+ //create the queue to send/receive Process ID between processes
+ RMsgQueue<TProcessId> messageQueueProcId;
+ User::LeaveIfError(messageQueueProcId.Open(EProcSlotMsgQueueProcId, EOwnerProcess));
+ CleanupClosePushL(messageQueueProcId);
+
+ if(aIdx == 0)
+ {
+ // Sending Process ID to other process... so that the other process can kill it.
+ TProcessId procId = RProcess().Id();
+ messageQueueProcId.SendBlocking(procId);
+ CleanupStack::PopAndDestroy(&messageQueueProcId);
+ //go into indefinite loop which will be terminated by the second process
+ for(;;) { }
+ }
+ else
+ {
+ TProcessId procId;
+ messageQueueProcId.ReceiveBlocking(procId);
+ CleanupStack::PopAndDestroy(&messageQueueProcId);
+
+ RProcess process;
+ ASSERT_TRUE(process.Open(procId) == KErrNone);
+ process.Kill(KErrNone);
+ process.Close();
+
+ // small delay to ensure the kernel finishes the clean-up
+ User::After(1*1000*1000); // 1 second
+ }
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-EGL-0439
+
+@SYMTestPriority 1
+
+@SYMPREQ 2637
+
+@SYMTestCaseDesc
+ OOM test Free VG/Egl/Sg Images while the process which owns them exits gracefully
+
+@SYMTestActions
+Environmental settings:
+ Image Size: w50 h50
+ List of simulated load: 0%
+ List of pixel formats
+ESgPixelFormatARGB_8888
+ Client process priorities - all the same
+ Client process random parameters:
+- None
+
+The creation of RSgImages and launching of processes is along the lines of the method outlined in GRAPHICS-EGL-RSGIMAGE_LITE-0406
+
+ From the main process:
+ For i = 0 to N
+ Spawn 1 client process.
+ Signal client process to start by use of a semaphore
+ Wait until client process exits
+ If the test fails not due to the memory allocation record an error code to the log file then set a test result as a failure and skip further actions.
+ End loop
+ Exit
+
+ From client process A:
+ Get EGL display
+ Initialize EGL
+ Open RSgDriver
+ Create context, pbuffer surface.
+ Make pbuffer surface current for the given context
+ Loop until exit condition met
+ Start loop:
+Create SgImage
+Create EglImage with underlying SgImage
+ Create VgImage with underlying EglImage
+ Exit condition Sg/Egl/Vg image creation has failed.
+End loop:
+ Destroy the pbuffer surface
+Log the last iteration number and exact operation which precedes a failure.
+Close all allocated graphics resources (Sg/Egl/Vg images)
+In the environment supporting NOK_resource_profiling2 extension, retrieve for further analyzes the following GPU profiling data (if available):
+ Total memory
+ Used memory
+ Process ID
+ Process used private memory
+ Process used shared memory
+
+Terminate EGL
+Close RSgDriver
+
+@SYMTestExpectedResults
+For each step from 0 to N in the main process,
+- Image allocation failure must happen at approximately the same iteration in process A.
+ MaxIterationNumber MinIterationNumber < Threashold, where Treashold will not
+ exceeds 5 and exact value to be defined during implementation.
+- GPU memory usage retrieved through NOK_resource_profiling2 extension, if available,
+ is consistent and doesnt decrease over the time.
+ MaxGPUMemoryUsage MinGPUMemoryUsage < Threshold, where Threshold will not exceed
+ 5 and exact value to be defined during implementation.
+*/
+TVerdict CEglTest_OOM_CloseVGImage::doTestStepL()
+ {
+ SetTestStepID(_L("GRAPHICS-EGL-0439"));
+ SetTestStepName(KOOM_CloseVGImage);
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseVGImage::doTestStepL"));
+
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseVGImage 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)
+ {
+ // if the test fails not due to the memory allocation, then skip further actions
+ for(TInt index = 0; (index < iNumIterations) && (TestStepResult()== EPass); index++)
+ {
+ // launch 1 process
+ Test_MultiProcessL(KEglTestStepDllName, 1, TestStepName());
+ RetrieveExtensionDataL();
+ }
+ CheckDeviation();
+ }
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ RecordTestResultL();
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+void CEglTest_OOM_CloseVGImage::doProcessFunctionL(TInt aIdx)
+ {
+ INFO_PRINTF2(_L("CEglTest_OOM_CloseVGImage::doProcessFunctionL, Process %d"),aIdx);
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ GetDisplayL();
+ CreateEglSessionL(aIdx);
+ iEglSess->InitializeL();
+ iEglSess->OpenSgDriverL();
+
+ //create a dummy surface and context for the purpose of enabling use of VG
+ TEglTestConfig pbufferFormat = EglTestConversion::VgFormatToPBufferSurfaceFormat(EglTestConversion::PixelFormatToVgFormat(iPixelFormat));
+ EGLConfig currentConfig = 0;
+ TRAPD(res, currentConfig = iEglSess->GetConfigExactMatchL( pbufferFormat ));
+ User::LeaveIfError(res);
+
+ iEglSess->CreatePbufferSurfaceAndMakeCurrentL(currentConfig, iImageSize, EGL_OPENVG_API);
+ TInt index = 0;
+ TSgImageInfo imageInfo;
+ imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
+ imageInfo.iPixelFormat = iPixelFormat;
+ imageInfo.iSizeInPixels = iImageSize;
+
+ for(;;++index)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(imageInfo, NULL);
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), index, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ iSgImages.AppendL(sgImage);
+
+ EGLImageKHR eglImage = iEglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&sgImage,const_cast<EGLint *> (KEglImageAttribsPreservedTrue));
+ EGLint eglError = eglGetError();
+ if((eglImage == EGL_NO_IMAGE_KHR) || (eglError != EGL_SUCCESS))
+ {
+ INFO_PRINTF4(_L("***Fail to create EGLImage after %d attempts, error: %d, expected: %d"), index, eglError, EGL_BAD_ALLOC);
+ ASSERT_TRUE(eglError == EGL_BAD_ALLOC);
+ break;
+ }
+ iEglImages.AppendL(eglImage);
+
+ VGImage vgImage = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImage);
+ VGErrorCode vgError = vgGetError();
+ if(vgImage == VG_INVALID_HANDLE || (vgError != VG_NO_ERROR))
+ {
+ INFO_PRINTF4(_L("***Fail to create VGImage after %d attempts, error: %d, expected: %d"), index, vgError, VG_OUT_OF_MEMORY_ERROR);
+ ASSERT_TRUE(vgError == VG_OUT_OF_MEMORY_ERROR);
+ break;
+ }
+ iVgImages.AppendL(vgImage);
+ }
+
+ SendIndexToMainProcessL(index);
+
+ //now clean everything
+ CleanGraphicsResources();
+ iEglSess->CloseSgDriver();
+ CleanAll();
+#endif
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-EGL-0440
+
+@SYMTestPriority 1
+
+@SYMPREQ 2637
+
+@SYMTestCaseDesc
+ OOM test Free SgImages/Pixmap surfaces while the process which owns them is terminated
+
+@SYMTestActions
+Environmental settings:
+ Image Size: w50 h50
+ List of simulated load: 0%
+ List of pixel formats
+ESgPixelFormatARGB_8888
+ Client process priorities - all the same
+ Client process random parameters:
+- None
+
+The creation of RSgImages and launching of processes is along the lines of the method outlined in GRAPHICS-EGL-RSGIMAGE_LITE-0406
+
+ From the main process:
+ For i = 0 to N
+ Spawn 2 client processes A and B.
+ Signal all client processes to start by use of a semaphore
+ Wait until client processes exit
+ If the test fails not due to the memory allocation record an error code to the log file then set a test result as a failure and skip further actions.
+ End loop
+ Exit
+
+ From client process A:
+ Get EGL display
+ Initialize EGL
+ Open RSgDriver
+ Loop until exit condition met
+ Start loop:
+ Create SgImage
+ Create Pixmap surface with underlying SgImage
+ Exit condition SgImage/Pixmap surface creation has failed.
+ End loop:
+ Log the last iteration number and exact operation which precedes a failure.
+ In the environment supporting NOK_resource_profiling2 extension retrieve for further analyzes the following GPU profiling data (if available):
+ Total memory
+ Used memory
+ Process ID
+ Process used private memory
+ Process used shared memory
+ Make the process busy by putting it into the indefinite loop.
+
+ From client process B:
+ Wait until process A fails with the image/surface creation.
+ Terminate the process A.
+
+@SYMTestExpectedResults
+For each step from 0 to N in the main process,
+- Image or surface allocation failure must happen at approximately the same iteration
+ in process A. MaxIterationNumber MinIterationNumber < Threashold,
+ where Treashold will not exceeds 5 and exact value to be defined during implementation.
+- GPU memory usage retrieved through NOK_resource_profiling2 extension, if available,
+ is consistent and doesnt decrease over the time.
+ MaxGPUMemoryUsage MinGPUMemoryUsage < Threshold, where Threshold will not exceed
+ 5 and exact value to be defined during implementation.
+*/
+TVerdict CEglTest_OOM_ClosePixmapSurfaceWithTermination::doTestStepL()
+ {
+ SetTestStepID(_L("GRAPHICS-EGL-0438"));
+ SetTestStepName(KOOM_ClosePixmapSurfaceWithTermination);
+ INFO_PRINTF1(_L("CEglTest_OOM_ClosePixmapSurfaceWithTermination::doTestStepL"));
+
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ INFO_PRINTF1(_L("CEglTest_OOM_ClosePixmapSurfaceWithTermination 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)
+ {
+ // if the test fails not due to the memory allocation, then skip further actions
+ for(TInt index = 0; (index < iNumIterations) && (TestStepResult()== EPass); index++)
+ {
+ // launch 2 processes
+ Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
+ RetrieveExtensionDataL();
+ }
+ CheckDeviation();
+ }
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ RecordTestResultL();
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+void CEglTest_OOM_ClosePixmapSurfaceWithTermination::doProcessFunctionL(TInt aIdx)
+ {
+ INFO_PRINTF2(_L("CEglTest_OOM_ClosePixmapSurfaceWithTermination::doProcessFunctionL, Process %d"),aIdx);
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ if(aIdx == 0)
+ {
+ GetDisplayL();
+ CreateEglSessionL(aIdx);
+ iEglSess->InitializeL();
+ iEglSess->OpenSgDriverL();
+
+ TInt index = 0;
+ TSgImageInfo imageInfo;
+ imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
+ imageInfo.iPixelFormat = iPixelFormat;
+ imageInfo.iSizeInPixels = iImageSize;
+
+ for(;;++index)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(imageInfo, NULL);
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), index, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+
+ EGLConfig currentConfig = 0;
+ const EGLint KAttrib[] = { EGL_MATCH_NATIVE_PIXMAP, (TInt)&sgImage,
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
+ EGL_NONE };
+
+ EGLint config_size;
+ ASSERT_EGL_TRUE(eglChooseConfig(iDisplay,KAttrib,¤tConfig,1,&config_size));
+ ASSERT_TRUE(currentConfig!=0);
+
+ // Create a pixmap surface from the native image
+ EGLSurface surface = eglCreatePixmapSurface(iDisplay, currentConfig, &sgImage, NULL);
+ EGLint eglError = eglGetError();
+ if((surface == EGL_NO_SURFACE) || (eglError != EGL_SUCCESS))
+ {
+ INFO_PRINTF4(_L("***Fail to create Pixmap surface after %d attempts, error: %d, expected: %d"), index, eglError, EGL_BAD_ALLOC);
+ ASSERT_TRUE(eglError == EGL_BAD_ALLOC);
+ break;
+ }
+ } //for
+ SendIndexToMainProcessL(index);
+ }
+ Rendezvous(aIdx);
+
+ //create the queue to send/receive Process ID between processes
+ RMsgQueue<TProcessId> messageQueueProcId;
+ User::LeaveIfError(messageQueueProcId.Open(EProcSlotMsgQueueProcId, EOwnerProcess));
+ CleanupClosePushL(messageQueueProcId);
+
+ if(aIdx == 0)
+ {
+ // Sending Process ID to other process... so that the other process can kill it.
+ TProcessId procId = RProcess().Id();
+ messageQueueProcId.SendBlocking(procId);
+ CleanupStack::PopAndDestroy(&messageQueueProcId);
+ //go into indefinite loop which will be terminated by the second process
+ for(;;) { }
+ }
+ else
+ {
+ TProcessId procId;
+ messageQueueProcId.ReceiveBlocking(procId);
+ CleanupStack::PopAndDestroy(&messageQueueProcId);
+
+ RProcess process;
+ ASSERT_TRUE(process.Open(procId) == KErrNone);
+ process.Kill(KErrNone);
+ process.Close();
+
+ // small delay to ensure the kernel finishes the clean-up
+ User::After(1*1000*1000); // 1 second
+ }
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-EGL-0441
+
+@SYMTestPriority 1
+
+@SYMPREQ 2637
+
+@SYMTestCaseDesc
+ OOM test Free SgImages/Pixmap surfaces while the process which owns them exits gracefully
+
+@SYMTestActions
+Environmental settings:
+ Image Size: w50 h50
+ List of simulated load: 0%
+ List of pixel formats
+ESgPixelFormatARGB_8888
+ Client process priorities - all the same
+ Client process random parameters:
+- None
+
+The creation of RSgImages and launching of processes is along the lines of the method outlined in GRAPHICS-EGL-RSGIMAGE_LITE-0406
+
+ From the main process:
+ For i = 0 to N
+ Spawn 1 client process.
+ Signal client process to start by use of a semaphore
+ Wait until client process exits
+ If the test fails not due to the memory allocation record an error code to the log file then set a test result as a failure and skip further actions.
+ End loop
+ Exit
+
+ From client process A:
+ Get EGL display
+ Initialize EGL
+ Open RSgDriver
+ Loop until exit condition met
+ Start loop:
+ Create SgImage
+ Create Pixmap surface with underlying SgImage
+ Exit condition SgImage/Pixmap surface creation has failed.
+ End loop:
+ Log the last iteration number and exact operation which precedes a failure.
+ CLose all allocated graphics resources (SgImages/Pixmap surfaces)
+ In the environment supporting NOK_resource_profiling2 extension retrieve for further analyzes the following GPU profiling data (if available):
+ Total memory
+ Used memory
+ Process ID
+ Process used private memory
+ Process used shared memory
+ Terminate EGL
+ Close RSgDriver
+
+@SYMTestExpectedResults
+For each step from 0 to N in the main process,
+- Image or surface allocation failure must happen at approximately the same iteration in process A.
+ MaxIterationNumber MinIterationNumber < Threashold,
+ where Treashold will not exceeds 5 and exact value to be defined during implementation.
+- GPU memory usage retrieved through NOK_resource_profiling2 extension,
+ if available, is consistent and doesnt decrease over the time.
+*/
+TVerdict CEglTest_OOM_ClosePixmapSurface::doTestStepL()
+ {
+ SetTestStepID(_L("GRAPHICS-EGL-0441"));
+ SetTestStepName(KOOM_ClosePixmapSurface);
+ INFO_PRINTF1(_L("CEglTest_OOM_ClosePixmapSurface::doTestStepL"));
+
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ INFO_PRINTF1(_L("CEglTest_OOM_ClosePixmapSurface 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)
+ {
+ // if the test fails not due to the memory allocation, then skip further actions
+ for(TInt index = 0; (index < iNumIterations) && (TestStepResult()== EPass); index++)
+ {
+ // launch 1 process
+ Test_MultiProcessL(KEglTestStepDllName, 1, TestStepName());
+ RetrieveExtensionDataL();
+ } //for
+ CheckDeviation();
+ }
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ RecordTestResultL();
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+void CEglTest_OOM_ClosePixmapSurface::doProcessFunctionL(TInt aIdx)
+ {
+ INFO_PRINTF2(_L("CEglTest_OOM_ClosePixmapSurface::doProcessFunctionL, Process %d"),aIdx);
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ GetDisplayL();
+ CreateEglSessionL(aIdx);
+ iEglSess->InitializeL();
+ iEglSess->OpenSgDriverL();
+
+ TInt index = 0;
+ TSgImageInfo imageInfo;
+ imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
+ imageInfo.iPixelFormat = iPixelFormat;
+ imageInfo.iSizeInPixels = iImageSize;
+
+ for(;;++index)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(imageInfo, NULL);
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), index, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ iSgImages.AppendL(sgImage);
+
+ EGLConfig currentConfig = 0;
+ const EGLint KAttrib[] = { EGL_MATCH_NATIVE_PIXMAP, (TInt)&sgImage,
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
+ EGL_NONE };
+
+ EGLint config_size;
+ ASSERT_EGL_TRUE(eglChooseConfig(iDisplay,KAttrib,¤tConfig,1,&config_size));
+ ASSERT_TRUE(currentConfig!=0);
+
+ // Create a pixmap surface from the native image
+ EGLSurface surface = eglCreatePixmapSurface(iDisplay, currentConfig, &sgImage, NULL);
+ EGLint eglError = eglGetError();
+ if((surface == EGL_NO_SURFACE) || (eglError != EGL_SUCCESS))
+ {
+ INFO_PRINTF4(_L("***Fail to create Pixmap surface after %d attempts, error: %d, expected: %d "), index, eglError, EGL_BAD_ALLOC);
+ ASSERT_TRUE(eglError == EGL_BAD_ALLOC);
+ break;
+ }
+ iSurfaces.AppendL(surface);
+ } //for
+ SendIndexToMainProcessL(index);
+ //now clean everything
+ CleanGraphicsResources();
+ iEglSess->CloseSgDriver();
+ CleanAll();
+#endif
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-EGL-0442
+
+@SYMTestPriority 1
+
+@SYMPREQ 2637
+
+@SYMTestCaseDesc
+ OOM test Check SgImages are removed when SgImage handles in multiple processes are closed
+
+@SYMTestActions
+Environmental settings:
+ Image Size: as per ini file
+ List of simulated load: 0%
+ List of pixel formats
+ESgPixelFormatARGB_8888
+ Client process priorities - all the same
+ Client process random parameters:
+- None
+
+The creation of RSgImages and launching of processes is along the lines of the method outlined in GRAPHICS-EGL-RSGIMAGE_LITE-0406
+
+ From the main process:
+ Spawn 2 client processes A and B.
+ Wait until client processes exit
+ If the test fails not due to the memory allocation record an error code to the log file then set a test result as a failure and skip further actions.
+ End loop
+ Exit
+
+ From client process A:
+ Get EGL display
+ Initialize EGL
+ Open RSgDriver
+ Loop until exit condition met
+ Start loop:
+ Create SgImage
+ Exit condition SgImage surface creation has failed.
+ End loop:
+ Make the process busy by putting it into the indefinite loop.
+
+ From client process B:
+ Start loop:
+ Open SgImage
+ Close SgImage
+ End loop:
+
+ From client process A:
+ Start loop:
+ Close SgImage
+ End loop:
+ Check all memory has been deallocated by starting a second loop
+ Start loop 2:
+ Create SgImage
+ Exit condition SgImage surface creation has failed.
+ End loop:
+ Check that the amount of images created within this loop 2 is similar to loop 1,
+ meaning that all images were correctly freed.
+ Cleanup everything
+
+ Terminate process A
+ Terminate process B
+
+@SYMTestExpectedResults
+For each step from 0 to N in the main process,
+- Image or surface allocation failure must happen at approximately the same iteration
+ in process A.
+*/
+TVerdict CEglTest_OOM_CloseSgImageDifferentProcess::doTestStepL()
+ {
+ SetTestStepID(_L("GRAPHICS-EGL-0442"));
+ SetTestStepName(KOOM_CloseSgImageDifferentProcess);
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseSgImageDifferentProcess::doTestStepL"));
+
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseSgImageDifferentProcess 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());
+ }
+ INFO_PRINTF1(_L("Exit: CEglTest_OOM_CloseSgImageDifferentProcess::doTestStepL"));
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ RecordTestResultL();
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+void CEglTest_OOM_CloseSgImageDifferentProcess::doProcessFunctionL(TInt aIdx)
+ {
+ INFO_PRINTF2(_L("CEglTest_OOM_CloseSgImageDifferentProcess::doProcessFunctionL, Process %d"),aIdx);
+#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ GetDisplayL();
+ CreateEglSessionL(aIdx);
+ iEglSess->InitializeL();
+ iEglSess->OpenSgDriverL();
+
+ //create the queue to send/receive SgImage ID between processes
+ RMsgQueue<TSgDrawableId> messageQueueSgId;
+ User::LeaveIfError(messageQueueSgId.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
+ CleanupClosePushL(messageQueueSgId);
+
+ // create as many sgimages until it reaches out of memory
+ TInt numImages = 0;
+ if(aIdx == 0)
+ {
+ for(;;++numImages)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(TSgImageInfo(iImageSize, KOOMPixelFormat, ESgUsageBitOpenVgImage));
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), numImages, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ iSgImages.AppendL(sgImage);
+ }
+ }
+
+ // Send to process B how many images it needs to wait for
+ if(aIdx == 0)
+ {
+ // send a TInt as a fake SgImage Id
+ messageQueueSgId.SendBlocking(reinterpret_cast<TSgDrawableId&>(numImages));
+ }
+ else if (aIdx == 1)
+ {
+ // receive the fake SgImage Id and convert it to a TInt
+ TSgDrawableId fakeId;
+ messageQueueSgId.ReceiveBlocking(fakeId);
+ numImages = reinterpret_cast<TInt&>(fakeId);
+ }
+
+ // Wait for both processes to reach this point
+ Rendezvous(aIdx);
+
+ // Now process B knows how many images needs to wait for
+ if(aIdx == 0)
+ {
+ for(TInt index = 0; index<numImages; ++index)
+ {
+ // send Id to other process
+ messageQueueSgId.SendBlocking(iSgImages[index].Id());
+ }
+ }
+ else if(aIdx == 1)
+ {
+ for(TInt index = 0; index<numImages; ++index)
+ {
+ // receive Id from other process
+ TSgDrawableId sgImageId;
+ messageQueueSgId.ReceiveBlocking(sgImageId);
+
+ // open sgImage with received Id
+ RSgImage sgImage;
+ ASSERT_EQUALS(sgImage.Open(sgImageId), KErrNone);
+
+ // close SgImage just created
+ sgImage.Close();
+ }
+ }
+
+ // Wait for both processes to reach this point
+ Rendezvous(aIdx);
+
+ // delete all sgImages created in first process
+ if(aIdx == 0)
+ {
+ CleanGraphicsResources();
+ }
+
+ // create (again) as many sgimages until it reaches out of memory
+ // note that process B needs to be alive (hence the Rendezvous further down)
+ if(aIdx == 0)
+ {
+ TInt numImages2 = 0;
+ for(;;++numImages2)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(TSgImageInfo(iImageSize, KOOMPixelFormat, ESgUsageBitOpenVgImage));
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), numImages2, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ iSgImages.AppendL(sgImage);
+ }
+ // clean up these images, we don't really need them
+ CleanGraphicsResources();
+
+ // check numbers...
+ INFO_PRINTF2(_L("***Num sgImages created first time: %d."), numImages);
+ INFO_PRINTF2(_L("***Num sgImages created second time: %d."), numImages2);
+ TInt deviation = Abs(((numImages2*100) / numImages) - 100);
+ ASSERT_TRUE(deviation < KOOMSgImageDeviation);
+ INFO_PRINTF3(_L("***Deviation: %d%% (must be less than %d%%)"), deviation, KOOMSgImageDeviation);
+
+ // This test does not need to send anything, but since OOM test framework expects something
+ // we can send a fake index so that the test is not waiting for it forever.
+ const TInt KTestNotUsedData = 0;
+ SendIndexToMainProcessL(KTestNotUsedData);
+ }
+
+ // Wait for both processes to reach this point
+ Rendezvous(aIdx);
+
+ //now clean everything
+ CleanupStack::PopAndDestroy(&messageQueueSgId);
+ CleanGraphicsResources();
+ iEglSess->CloseSgDriver();
+ CleanAll();
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-EGL-0443
+
+@SYMTestPriority 1
+
+@SYMPREQ 2637
+
+@SYMTestCaseDesc
+ OOM test Check SgImages are removed when SgImage handles in multiple processes are closed
+
+@SYMTestActions
+Environmental settings:
+ Image Size: as per ini file
+ List of simulated load: 0%
+ List of pixel formats
+ESgPixelFormatARGB_8888
+ Client process priorities - all the same
+ Client process random parameters:
+- None
+
+The creation of RSgImages and launching of processes is along the lines of the method outlined in GRAPHICS-EGL-RSGIMAGE_LITE-0406
+
+ From the main process:
+ From client process A:
+ Get EGL display
+ Initialize EGL
+ Open RSgDriver
+ Loop until exit condition met
+ Start loop:
+ Create SgImage
+ Exit condition SgImage surface creation has failed.
+ End loop:
+ Start loop:
+ Open SgImage
+ Close SgImage
+ End loop:
+ Start loop:
+ Close SgImage
+ End loop:
+ Check all memory has been deallocated by starting a second loop
+ Start loop 2:
+ Create SgImage
+ Exit condition SgImage surface creation has failed.
+ End loop:
+ Check that the amount of images created within this loop 2 is similar to loop 1,
+ meaning that all images were correctly freed.
+ Cleanup everything
+
+@SYMTestExpectedResults
+For each step from 0 to N in the main process,
+- Image or surface allocation failure must happen at approximately the same iteration
+ in process A.
+*/
+TVerdict CEglTest_OOM_CloseSgImageSameThread::doTestStepL()
+ {
+ SetTestStepID(_L("GRAPHICS-EGL-0443"));
+ SetTestStepName(KOOM_CloseSgImageSameThread);
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseSgImageSameThread::doTestStepL"));
+
+#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+ INFO_PRINTF1(_L("CEglTest_OOM_CloseSgImageSameThread 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)
+ {
+ GetDisplayL();
+ CreateEglSessionL(0);
+ iEglSess->InitializeL();
+ iEglSess->OpenSgDriverL();
+
+ // create as many sgimages until it reaches out of memory
+ TInt numImages = 0;
+ for(;;++numImages)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(TSgImageInfo(iImageSize, KOOMPixelFormat, ESgUsageBitOpenVgImage));
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), numImages, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ iSgImages.AppendL(sgImage);
+ }
+
+ //open a duplicate handle for the created images (can close straightaway)
+ for(TInt index = 0; index<numImages; ++index)
+ {
+ RSgImage sgImage;
+ ASSERT_EQUALS(sgImage.Open(iSgImages[index].Id()), KErrNone);
+ // close SgImage just created
+ sgImage.Close();
+ }
+
+ // clean up all (original) images
+ CleanGraphicsResources();
+
+ // create (again) as many sgimages until it reaches out of memory
+ TInt numImages2 = 0;
+ for(;;++numImages2)
+ {
+ RSgImage sgImage;
+ TInt res = sgImage.Create(TSgImageInfo(iImageSize, KOOMPixelFormat, ESgUsageBitOpenVgImage));
+ if(res != KErrNone || sgImage.IsNull())
+ {
+ INFO_PRINTF5(_L("***Fail to create RSgImage after %d attempts, error: %d, expected: %d or %d"), numImages2, res, KErrNoMemory, KErrNoGraphicsMemory);
+ ASSERT_TRUE((res == KErrNoMemory) || (res == KErrNoGraphicsMemory));
+ break;
+ }
+ iSgImages.AppendL(sgImage);
+ }
+
+ // clean up everything now
+ CleanGraphicsResources();
+ iEglSess->CloseSgDriver();
+ CleanAll();
+
+ // check numbers...
+ INFO_PRINTF2(_L("***Num sgImages created first time: %d."), numImages);
+ INFO_PRINTF2(_L("***Num sgImages created second time: %d."), numImages2);
+ TInt deviation = Abs(((numImages2*100) / numImages) - 100);
+ ASSERT_TRUE(deviation < KOOMSgImageDeviation);
+ INFO_PRINTF3(_L("***Deviation: %d%% (must be less than %d%%)"), deviation, KOOMSgImageDeviation);
+ }
+ INFO_PRINTF1(_L("Exit: CEglTest_OOM_CloseSgImageSameThread::doTestStepL"));
+#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
+
+ RecordTestResultL();
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+