os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_remote.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_remote.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1120 @@
1.4 +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +/**
1.20 + @file
1.21 + @test
1.22 + @internalComponent - Internal Symbian test code
1.23 +*/
1.24 +
1.25 +#include <e32std.h>
1.26 +#include <e32math.h>
1.27 +#include <e32atomics.h>
1.28 +#include "egltest_endpoint_engine.h"
1.29 +#include "egltest_endpoint_images.h"
1.30 +#include "egltest_surface.h"
1.31 +#include "egltest_parameters.h"
1.32 +
1.33 +
1.34 +const TInt KMemStatsReserve = 3;
1.35 +
1.36 +CEgltest_Remote_Engine::CEgltest_Remote_Engine()
1.37 + : CRemoteTestStepBase(ETestUidEndpointEngine), iTestVerdict(ERtvPass), iLogging(EFalse), iSurface(0)
1.38 + {
1.39 + iMainThreadHeap = &User::Heap(); // ?? Is this the right heap ??
1.40 + for (TInt i = 0; i < KMaxEndpoints; i++)
1.41 + {
1.42 + iEndpoints[i] = EGL_NO_ENDPOINT_NOK;
1.43 + iEglImage[i] = EGL_NO_IMAGE_KHR;
1.44 + iVgImage[i] = NULL;
1.45 + iRequestStatus[i] = KRequestPending;
1.46 + }
1.47 + ipfnEglQueryProfilingDataNOK = reinterpret_cast<PFNEGLQUERYPROFILINGDATANOKPROC>(eglGetProcAddress("eglQueryProfilingDataNOK"));
1.48 + if (ipfnEglQueryProfilingDataNOK)
1.49 + {
1.50 + RDebug::Printf("%s:%d: found eglQueryProfilingDataNOK function");
1.51 + }
1.52 + }
1.53 +
1.54 +CEgltest_Remote_Engine::~CEgltest_Remote_Engine()
1.55 + {
1.56 + // Note: This is run from a different thread an on a different heap than the one
1.57 + // used during the execution of DoRunRemoteTestCaseL(). So any allocation done
1.58 + // during DoRunRemoteTestCaseL must be de-allocated in DoEndRemoteTestStepL()
1.59 + }
1.60 +
1.61 +TRemoteTestVerdict CEgltest_Remote_Engine::DoStartRemoteTestStepL(
1.62 + const TRemoteTestParams& aParams)
1.63 + {
1.64 + iMainThreadHeap = &User::Heap();
1.65 +
1.66 + iMemoryStats.ReserveL(KMemStatsReserve);
1.67 + iLogging = EFalse;
1.68 + iLogErrors = aParams.iEndpointEngineConfig.iLogErrors;
1.69 + return ERtvPass;
1.70 + }
1.71 +
1.72 +TRemoteTestVerdict CEgltest_Remote_Engine::DoEndRemoteTestStepL(
1.73 + const TRemoteTestParams& /* aParams */)
1.74 + {
1.75 + iMemoryStats.Close();
1.76 + delete iSurface;
1.77 + return ERtvPass;
1.78 + }
1.79 +
1.80 +void CEgltest_Remote_Engine::CheckReturn(TInt aRetval,
1.81 + const TEngineTestCase& aEngineTestCase, TInt aFailValue,
1.82 + const TText* aFailSymbol, const TText* aFunction)
1.83 + {
1.84 + TBool isEqual = (aRetval == aFailValue);
1.85 + TBool expectFail = (aEngineTestCase.iFlags & EExpectFailureMask) != 0;
1.86 +
1.87 + EGLint err = eglGetError();
1.88 + if (err != aEngineTestCase.iErrorExpected)
1.89 + {
1.90 + if (iLogErrors)
1.91 + {
1.92 + REMOTE_ERR_PRINTF3(_L("testcase failed: expected %04x, got %04x"), aEngineTestCase.iErrorExpected, err);
1.93 + }
1.94 + iTestVerdict = ERtvFail;
1.95 + }
1.96 +
1.97 + if (!isEqual && expectFail)
1.98 + {
1.99 + if (iLogErrors)
1.100 + {
1.101 + REMOTE_ERR_PRINTF5(
1.102 + _L("return value when failing from %s is not expected fail value %s (%d). Value returned is %d"),
1.103 + aFunction, aFailSymbol, aFailValue, aRetval);
1.104 + }
1.105 + iTestVerdict = ERtvFail;
1.106 + }
1.107 + else if (isEqual && !expectFail)
1.108 + {
1.109 + if (iLogErrors)
1.110 + {
1.111 + REMOTE_ERR_PRINTF5(
1.112 + _L("return value when succeeding from %s is equal to expected fail value %s (%d). Value returned is %d"),
1.113 + aFunction, aFailSymbol, aFailValue, aRetval);
1.114 + }
1.115 + iTestVerdict = ERtvFail;
1.116 + }
1.117 + if (isEqual != expectFail)
1.118 + {
1.119 + if (iLogErrors)
1.120 + {
1.121 + REMOTE_ERR_PRINTF4(_L("Unexpected result for %s, failvalue is %s, flags = %d"),
1.122 + aFunction, aFailSymbol,
1.123 + aEngineTestCase.iFlags);
1.124 + }
1.125 + iTestVerdict = ERtvFail;
1.126 + }
1.127 + // Now check
1.128 + if (expectFail && err == EGL_SUCCESS)
1.129 + {
1.130 + if (iLogErrors)
1.131 + {
1.132 + REMOTE_ERR_PRINTF2(_L("Got EGL_SUCCESS in error when calling %s, when we expected an error"),
1.133 + aFunction);
1.134 + }
1.135 + iTestVerdict = ERtvFail;
1.136 + }
1.137 + // Didn't expect to fail, so we
1.138 + else if (!expectFail && err != EGL_SUCCESS)
1.139 + {
1.140 + if (iLogErrors)
1.141 + {
1.142 + REMOTE_ERR_PRINTF3(_L("Got an error (%x) on successful call to %s, when expecting EGL_SUCCESS"),
1.143 + err, aFunction);
1.144 + }
1.145 + iTestVerdict = ERtvFail;
1.146 + }
1.147 + }
1.148 +
1.149 +#define CHECK_RETURN(retval, failval, func) \
1.150 + CheckReturn((retval), si, (failval), _S(#failval), func)
1.151 +
1.152 +#define CHECK_RETURN_CAST(retval, failval, func) \
1.153 + CheckReturn(reinterpret_cast<int>(retval), si, reinterpret_cast<int>(failval), _S(#failval), func)
1.154 +
1.155 +#define CHECK_BOOL_RET(func, funcName) \
1.156 +{ \
1.157 + EGLBoolean ret = EglEndpoint().func(dpy, endpoint); \
1.158 + CheckReturn(ret, si, EGL_FALSE, _S("EGL_FALSE"), _S(funcName)); \
1.159 +}
1.160 +
1.161 +void CEgltest_Remote_Engine::LogDump(const TEngineTestCase& aCase)
1.162 + {
1.163 + const TText *caseName = EngineCaseName(aCase.iCase);
1.164 +
1.165 + Log(((TText8*)__FILE__), __LINE__, ESevrInfo,
1.166 + _L("Performing subcase %d (%s), with flags=%d, err=%04x endpointidx=%d, image=%d, args=(%d, %d)"),
1.167 + aCase.iCase,
1.168 + caseName,
1.169 + aCase.iFlags,
1.170 + aCase.iErrorExpected,
1.171 + aCase.iEndpointIndex,
1.172 + aCase.iImageIndex,
1.173 + aCase.iArg1, aCase.iArg2);
1.174 + }
1.175 +
1.176 +TRemoteTestVerdict CEgltest_Remote_Engine::DoRunRemoteTestCaseL(
1.177 + TInt aTestCase, const TRemoteTestParams &aParams)
1.178 + {
1.179 + TRemoteTestArgs args;
1.180 + iTestVerdict = ERtvPass;
1.181 + const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
1.182 +
1.183 + CDisplayParams* displayParams = CDisplayParams::NewLC(!!(si.iFlags & EUseBadDisplay), eglGetDisplay(EGL_DEFAULT_DISPLAY));
1.184 + TInt dpyParamsCount = displayParams->Count();
1.185 + CEndpointParams* endpointParams = CEndpointParams::NewLC(!!(si.iFlags & EUseBadEndpoint), iEndpoints, KMaxEndpoints, si.iEndpointIndex);
1.186 + TInt endpointCount = endpointParams->Count();
1.187 + CImageParams* imageParams = CImageParams::NewLC(!!(si.iFlags & EUseBadEglImage), iEglImage, KMaxEndpoints, si.iImageIndex);
1.188 + TInt imageCount = imageParams->Count();
1.189 +
1.190 + for(TInt dpyIter = 0; dpyIter < dpyParamsCount; dpyIter++)
1.191 + {
1.192 + args.iDisplay = (*displayParams)[dpyIter];
1.193 + for(TInt epIter = 0; epIter < endpointCount; epIter++)
1.194 + {
1.195 + args.iEndpoint = (*endpointParams)[epIter];
1.196 +
1.197 + for(TInt imageIter = 0; imageIter < imageCount; imageIter++)
1.198 + {
1.199 + args.iImage = (*imageParams)[imageIter];
1.200 +
1.201 + RunCaseL(aTestCase, aParams, args);
1.202 + if (iLogErrors && iTestVerdict != ERtvPass || iLogging)
1.203 + {
1.204 + if (iTestVerdict != ERtvPass)
1.205 + {
1.206 + REMOTE_INFO_PRINTF1(_L("Test failed:"));
1.207 + }
1.208 + LogDump(si);
1.209 + REMOTE_INFO_PRINTF4(_L("Using values: display: %d, endpoint: %d, image: %d"),
1.210 + args.iDisplay, args.iEndpoint, args.iImage);
1.211 + }
1.212 + }
1.213 + }
1.214 + }
1.215 + CleanupStack::PopAndDestroy(3);
1.216 + return iTestVerdict;
1.217 + }
1.218 +
1.219 +
1.220 +void CEgltest_Remote_Engine::ActivateVgContextL()
1.221 + {
1.222 + if (!iSurface)
1.223 + {
1.224 + iSurface = CEglWindowSurface::NewL();
1.225 + iSurface->CreateL(EStandardSurface, TPoint(0, 110));
1.226 + }
1.227 + iSurface->ActivateL();
1.228 + }
1.229 +
1.230 +
1.231 +TInt CEgltest_Remote_Engine::FillGpuMemory()
1.232 + {
1.233 + TSurfaceIndex table[] =
1.234 + {
1.235 + ELargeSurface,
1.236 + EStandard128sqSurface,
1.237 + ESmallSurface,
1.238 + ETinySurface
1.239 + };
1.240 + const TInt KNumSurfaceTypes = sizeof(table) / sizeof(table[0]);
1.241 +
1.242 + TInt nSurfaces = 0;
1.243 + const TInt KMaxSurfaceAllocs = 1000;
1.244 + CSurface **surfaces = new CSurface*[KMaxSurfaceAllocs];
1.245 + TInt size = 0;
1.246 + ENGINE_ASSERT(surfaces);
1.247 + for(TInt i = 0; i < KNumSurfaceTypes; i++)
1.248 + {
1.249 + TInt err = KErrNone;
1.250 + while(err == KErrNone)
1.251 + {
1.252 + ENGINE_ASSERT(nSurfaces < KMaxSurfaceAllocs);
1.253 + CSurface* s = CSurface::SurfaceFactoryL(ESurfTypePBuffer);
1.254 + if (s)
1.255 + {
1.256 + TRAP(err, s->CreateL(table[i]));
1.257 + if (err == KErrNone)
1.258 + {
1.259 + surfaces[nSurfaces++] = s;
1.260 +// s->DrawContentL(TRgb(0x10, 0x20, 0xB0));
1.261 + size += s->SizeInBytes();
1.262 + }
1.263 + }
1.264 + }
1.265 + }
1.266 + RDebug::Printf("nSurfaces=%d", nSurfaces);
1.267 + while(nSurfaces)
1.268 + {
1.269 + delete surfaces[--nSurfaces];
1.270 + }
1.271 + delete [] surfaces;
1.272 + return size;
1.273 + }
1.274 +
1.275 +TInt CEgltest_Remote_Engine::CalculateAvailableGPUMemory()
1.276 + {
1.277 + TInt result = 0;
1.278 + if (ipfnEglQueryProfilingDataNOK)
1.279 + {
1.280 + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1.281 + ENGINE_ASSERT(display != EGL_NO_DISPLAY);
1.282 + TInt count;
1.283 + ipfnEglQueryProfilingDataNOK(
1.284 + display, EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
1.285 + NULL, 0, &count);
1.286 + ENGINE_ASSERT(count);
1.287 + TInt *mem = new TInt[count * 2];
1.288 + ENGINE_ASSERT(mem);
1.289 + TInt newCount;
1.290 + ipfnEglQueryProfilingDataNOK(
1.291 + display, EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
1.292 + mem, count, &newCount);
1.293 + ENGINE_ASSERT(newCount == count);
1.294 + for(TInt i = 0; i < count; i ++)
1.295 + {
1.296 + switch(mem[i*2])
1.297 + {
1.298 + case EGL_PROF_USED_MEMORY_NOK:
1.299 + // Assert that we only have one entry - if there are
1.300 + // more than one, we can't really know what is the "right" one.
1.301 + ENGINE_ASSERT(!result);
1.302 + result = mem[i*2+1];
1.303 + break;
1.304 + }
1.305 + }
1.306 + delete [] mem;
1.307 + }
1.308 + else
1.309 + {
1.310 +#if 1
1.311 + result = 1000;
1.312 +#else
1.313 + // This code currently causes a memory leak to be detected when the
1.314 + // remote thread is destroyed. This causes further tests to be skipped.
1.315 + // We disable this function at the moment, to allow other tests to run.
1.316 + result = FillGpuMemory();
1.317 +#endif
1.318 + }
1.319 + return result;
1.320 + }
1.321 +
1.322 +
1.323 +TInt CEgltest_Remote_Engine::CalculateAvailableHeapMemory()
1.324 + {
1.325 + TInt biggest = 0;
1.326 + return User::Heap().Available(biggest);
1.327 + }
1.328 +
1.329 +
1.330 +void CEgltest_Remote_Engine::CheckForMemoryLeaks()
1.331 + {
1.332 + TAvailableMemory mem;
1.333 + mem.iGpuMemAvailable = CalculateAvailableGPUMemory();
1.334 + mem.iHeapMemAvailable = CalculateAvailableHeapMemory();
1.335 +
1.336 + REMOTE_INFO_PRINTF3(_L("GPU memory available: %d, heapmemory available: %d"),
1.337 + mem.iGpuMemAvailable, mem.iHeapMemAvailable);
1.338 + if (iMemoryStats.Count() == KMemStatsReserve)
1.339 + {
1.340 + REMOTE_INFO_PRINTF2(_L("false positive HEAP leak possible, as reserved memory is exhausted... (%d)"), KMemStatsReserve);
1.341 + }
1.342 + TInt err = iMemoryStats.Append(mem);
1.343 + if (err)
1.344 + {
1.345 + REMOTE_ERR_PRINTF2(_L("CheckForMemoryLeaks could not append to iMemoryStats. err=%d"), err);
1.346 + }
1.347 + }
1.348 +
1.349 +void CEgltest_Remote_Engine::CheckForMemoryLeaksFinish()
1.350 + {
1.351 + TInt count = iMemoryStats.Count();
1.352 + if (count)
1.353 + {
1.354 + TReal sumGpu = 0.0;
1.355 + TReal sumHeap = 0.0;
1.356 +
1.357 + for(TInt i = 0; i < count; i++)
1.358 + {
1.359 + sumGpu += iMemoryStats[i].iGpuMemAvailable;
1.360 + sumHeap += iMemoryStats[i].iHeapMemAvailable;
1.361 + }
1.362 + REMOTE_INFO_PRINTF2(_L("CheckMemoryLeaksFinish - average = %6.2f"), sumGpu / count);
1.363 + REMOTE_INFO_PRINTF2(_L("CheckMemoryLeaksFinish - average = %6.2f"), sumHeap / count);
1.364 + }
1.365 + else
1.366 + {
1.367 + REMOTE_INFO_PRINTF1(_L("CheckMemoryLeaksFinish - no data collected"));
1.368 + }
1.369 + iMemoryStats.Close();
1.370 + }
1.371 +
1.372 +TRemoteTestVerdict ConvertToLocalVerdict(TInt aVerdict)
1.373 + {
1.374 + switch(aVerdict)
1.375 + {
1.376 + case EPass:
1.377 + return ERtvPass;
1.378 + case EFail:
1.379 + return ERtvFail;
1.380 + }
1.381 + return ERtvInconclusive;
1.382 + }
1.383 +
1.384 +void CEgltest_Remote_Engine::RunCaseL(TInt aTestCase, const TRemoteTestParams &aParams, const TRemoteTestArgs& aArgs)
1.385 + {
1.386 + const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
1.387 + EGLDisplay dpy = aArgs.iDisplay;
1.388 + EGLImageKHR image = aArgs.iImage;
1.389 + EGLEndpointNOK endpoint = aArgs.iEndpoint;
1.390 +
1.391 + switch (aTestCase)
1.392 + {
1.393 + case EInitializeCase:
1.394 + REMOTE_INFO_PRINTF1(_L("calling EglStartL()"));
1.395 + EglStartL();
1.396 + break;
1.397 +
1.398 + case ECreateEndpointCase:
1.399 + CreateEndpointCaseL(aParams, aArgs);
1.400 + break;
1.401 +
1.402 + case EAcquireImageCase:
1.403 + image = EglEndpoint().AcquireImage(dpy, endpoint);
1.404 + CHECK_RETURN(image, EGL_NO_IMAGE_KHR, _S("eglAcquireImage"));
1.405 + if (image != EGL_NO_IMAGE_KHR)
1.406 + {
1.407 + iEglImage[si.iEndpointIndex] = image;
1.408 + }
1.409 + break;
1.410 +
1.411 + case ECompareImageCase:
1.412 + if (iEglImage[si.iEndpointIndex] == EGL_NO_IMAGE_KHR)
1.413 + {
1.414 + REMOTE_ERR_PRINTF2(_L("Image at index %d is not a valid eglImage"), si.iEndpointIndex);
1.415 + iTestVerdict = ERtvFail;
1.416 + }
1.417 + else
1.418 + {
1.419 + ActivateVgContextL();
1.420 +
1.421 + CTestCFbsImage *image = CTestCFbsImage::NewL(si.iImageIndex);
1.422 + CleanupStack::PushL(image);
1.423 + CTestVgEglImage *vgImage = CTestVgEglImage::New(iEglImage[si.iEndpointIndex]);
1.424 + if (!vgImage)
1.425 + {
1.426 + REMOTE_INFO_PRINTF2(_L("Could not create vgimage from eglimage: endpointindex=%d"),
1.427 + si.iEndpointIndex);
1.428 + }
1.429 + else
1.430 + {
1.431 + CleanupStack::PushL(vgImage);
1.432 + TBool res = vgImage->CompareImageL(image, !!(si.iFlags & EExpectError));
1.433 + if (res != !(si.iFlags & EExpectError))
1.434 + {
1.435 + if (iLogErrors)
1.436 + {
1.437 + REMOTE_ERR_PRINTF1(_L("Pixel comparison failed...."));
1.438 + }
1.439 + iTestVerdict = ERtvFail;
1.440 + }
1.441 + else if (!(si.iFlags & EExpectError))
1.442 + {
1.443 + // Extra check that ANOTHER image doesn't match the image
1.444 + // we compared with.
1.445 + // This would detect when images have incorrect content or
1.446 + // the code for comparing images have been broken.
1.447 + TInt imageIndex2 = (si.iImageIndex + 1) % CTestImage::KImageCount;
1.448 + CTestCFbsImage *image2 = CTestCFbsImage::NewL(imageIndex2);
1.449 + CleanupStack::PushL(image2);
1.450 + res = vgImage->CompareImageL(image2, ETrue);
1.451 + if (res)
1.452 + {
1.453 + REMOTE_ERR_PRINTF1(_L("Pixel comparison didn't fail - two images the same?...."));
1.454 + iTestVerdict = ERtvFail;
1.455 + }
1.456 + CleanupStack::PopAndDestroy(image2);
1.457 + }
1.458 + CleanupStack::PopAndDestroy(vgImage);
1.459 + }
1.460 + CleanupStack::PopAndDestroy(image);
1.461 + }
1.462 + break;
1.463 +
1.464 + case EReleaseImageCase:
1.465 + ReleaseImageCaseL(aParams, aArgs);
1.466 + break;
1.467 +
1.468 + case EBeginStreamingCase:
1.469 + CHECK_BOOL_RET(EndpointBeginStreaming, "eglEndpointBeginStreaming");
1.470 + break;
1.471 +
1.472 + case EEndStreamingCase:
1.473 + CHECK_BOOL_RET(EndpointEndStreaming, "eglEndpointEndStreaming");
1.474 + break;
1.475 +
1.476 + case EDestroyEndpointCase:
1.477 + CHECK_BOOL_RET(DestroyEndpoint, "eglDestroyEndpoint");
1.478 + break;
1.479 +
1.480 + case EGetAttribCase:
1.481 + {
1.482 + TInt value = EglEndpoint().GetEndpointAttrib(dpy, endpoint, si.iArg1);
1.483 + // We can't use the macro CHECK_RETURN here, as the return value for
1.484 + // "success" can be any integer value, including "EGL_FALSE". So we can
1.485 + // only check when we expect failure.
1.486 + if (si.iFlags & EExpectFailureMask)
1.487 + {
1.488 + CheckReturn(value, si, EGL_FALSE,_S("EGL_FALSE") ,_S("eglGetEndpointAttrib"));
1.489 + }
1.490 + else
1.491 + {
1.492 + EGLint err = eglGetError();
1.493 + if (err != EGL_SUCCESS)
1.494 + {
1.495 + REMOTE_ERR_PRINTF2(_L("Got an error (%x) on successful call to eglGetEndpointAttrib, when expecting EGL_SUCCESS in error"),
1.496 + err);
1.497 + iTestVerdict = ERtvFail;
1.498 + }
1.499 + }
1.500 + if (value != si.iArg2)
1.501 + {
1.502 + REMOTE_ERR_PRINTF4(_L("GetEndpointAttrib(%04x), got %d, expected %d"), si.iArg1, value, si.iArg2);
1.503 + iTestVerdict = ERtvFail;
1.504 + }
1.505 + }
1.506 + break;
1.507 +
1.508 + case ESetAttribCase:
1.509 + {
1.510 + EGLBoolean ret = EglEndpoint().SetEndpointAttrib(dpy, endpoint, si.iArg1, si.iArg2);
1.511 + CHECK_RETURN(ret, EGL_FALSE, _S("eglSetEndpointAttrib"));
1.512 + }
1.513 + break;
1.514 +
1.515 + case EDestroyEglImageCase:
1.516 + {
1.517 + EGLBoolean ret = EglEndpoint().DestroyImage(dpy, image);
1.518 + CHECK_RETURN(ret, EGL_FALSE, _S("eglDestroyImageKHR"));
1.519 + }
1.520 + break;
1.521 +
1.522 + case ECreateVgImageCase:
1.523 + {
1.524 + // For a VgImage to be possible to create, we need to have a EglSurface.
1.525 + ActivateVgContextL();
1.526 +
1.527 + TRAPD(err, iVgImage[si.iImageIndex] = CTestVgEglImage::NewL(iEglImage[si.iEndpointIndex]));
1.528 + if ((si.iFlags & EExpectFailureMask) && err == KErrNone)
1.529 + {
1.530 + REMOTE_ERR_PRINTF1(_L("Successfully created VGImage when we expected an error"));
1.531 + iTestVerdict = ERtvFail;
1.532 + delete iVgImage[si.iImageIndex];
1.533 + iVgImage[si.iImageIndex] = NULL;
1.534 + }
1.535 + else if (!(si.iFlags & EExpectFailureMask) && err != KErrNone)
1.536 + {
1.537 + REMOTE_ERR_PRINTF1(_L("Failed to create VGImage when we expected to succeed"));
1.538 + iTestVerdict = ERtvFail;
1.539 + }
1.540 + }
1.541 + break;
1.542 +
1.543 + // Test that a vgImage can be used. We do NOT test the content for anything in particular, since
1.544 + // the current usage of this is to do checking on a vgImage after endpoint is destroyed, and the
1.545 + // specification is that the vgImage is undefined under this condition.
1.546 + case ETestVgImageValidCase:
1.547 + {
1.548 + ActivateVgContextL();
1.549 + CTestVgEglImage *vgImage = iVgImage[si.iImageIndex];
1.550 + if (!vgImage)
1.551 + {
1.552 + // Image not usable!
1.553 + REMOTE_ERR_PRINTF1(_L("VGImage is not present"));
1.554 + iTestVerdict = ERtvFail;
1.555 + }
1.556 + else
1.557 + {
1.558 + vgDrawImage(vgImage->VGImage());
1.559 + VGint err = vgGetError();
1.560 + if (err != VG_NO_ERROR)
1.561 + {
1.562 + iTestVerdict = ERtvFail;
1.563 + }
1.564 +#if 0
1.565 + TSize size = vgImage->Size();
1.566 + // Now read the pixels in four corners and the middle to check if the image is still "working".
1.567 + vgImage->Pixel(0, 0);
1.568 + vgImage->Pixel(size.iWidth-1, size.iHeight-1);
1.569 + vgImage->Pixel(0, size.iHeight-1);
1.570 + vgImage->Pixel(size.iWidth-1, 0);
1.571 + vgImage->Pixel(size.iWidth >> 1, size.iHeight >> 1);
1.572 +#endif
1.573 + }
1.574 + // If we get here, the image is "working" - we expect to panic or crash if it's not...
1.575 + }
1.576 + break;
1.577 +
1.578 + case EDestroyVgImageCase:
1.579 + delete iVgImage[si.iImageIndex];
1.580 + iVgImage[si.iImageIndex] = NULL;
1.581 + break;
1.582 +
1.583 + case ERequestNotificationCase:
1.584 + RequestNotificationL(aParams, aArgs);
1.585 + break;
1.586 +
1.587 + case ECancelNotificationCase:
1.588 + CHECK_BOOL_RET(EndpointCancelNotification, "eglEndpointCancelNotification");
1.589 + break;
1.590 +
1.591 + case EWaitForNotificationCase:
1.592 + {
1.593 + RTimer timer;
1.594 + TInt err = timer.CreateLocal();
1.595 + if (err != KErrNone)
1.596 + {
1.597 + REMOTE_INFO_PRINTF2(_L("Could not create timer. Error=%d"), err);
1.598 + iTestVerdict = ERtvFail;
1.599 + }
1.600 + else
1.601 + {
1.602 + TRequestStatus timerStatus = KRequestPending;
1.603 + timer.HighRes(timerStatus, si.iArg1);
1.604 + // Note that the requeststatus is set to KRequestPending by
1.605 + // eglEndpointRequestNotificationNOK(), so we don't do that
1.606 + // before waiting. See below for more comments.
1.607 + TRequestStatus *requestStatus = &iRequestStatus[si.iEndpointIndex];
1.608 + User::WaitForRequest(timerStatus, *requestStatus);
1.609 + TInt result = KErrNotReady; // Give it some ERROR value that is unlikely to happen later.
1.610 + timer.Cancel();
1.611 + timer.Close();
1.612 + if (timerStatus == KErrNone && *requestStatus == KRequestPending)
1.613 + {
1.614 + result = KErrTimedOut;
1.615 + }
1.616 + else
1.617 + {
1.618 + result = requestStatus->Int();
1.619 + }
1.620 + // Reset the request - this allows us to (ab-)use this request to
1.621 + // wait for things that aren't completing, etc.
1.622 + *requestStatus = KRequestPending;
1.623 + if ((si.iFlags & EExpectError) && result >= KErrNone)
1.624 + {
1.625 + iTestVerdict = ERtvFail;
1.626 + REMOTE_INFO_PRINTF1(_L("Expected failure, but result was a success"));
1.627 + }
1.628 + else if (!(si.iFlags & EExpectError) && result < KErrNone)
1.629 + {
1.630 + iTestVerdict = ERtvFail;
1.631 + REMOTE_INFO_PRINTF1(_L("Expected success, but result was a failure"));
1.632 + }
1.633 + if (result != si.iErrorExpected)
1.634 + {
1.635 + iTestVerdict = ERtvFail;
1.636 + REMOTE_INFO_PRINTF3(_L("EWaitForNotificationCase: Expected error %d, got %d"), si.iErrorExpected, result);
1.637 + }
1.638 + }
1.639 + }
1.640 + break;
1.641 +
1.642 + case EGetEndpointDirtyAreaCase:
1.643 + GetEndpointDirtyAreaL(aParams, aArgs);
1.644 + break;
1.645 +
1.646 + case ETerminateCase:
1.647 + REMOTE_INFO_PRINTF1(_L("calling EglEndL()"));
1.648 + EglEndL();
1.649 + break;
1.650 +
1.651 + // Memory leak checking functions.
1.652 + case ECheckForMemoryLeaks:
1.653 + CheckForMemoryLeaks();
1.654 + break;
1.655 +
1.656 + case ECheckForMemoryLeaksFinish:
1.657 + CheckForMemoryLeaksFinish();
1.658 + break;
1.659 +
1.660 +
1.661 + case EStartLoadThreadCase:
1.662 + StartThreadL(si.iEndpointIndex);
1.663 + break;
1.664 +
1.665 + case EEndLoadThreadCase:
1.666 + EndThread(si.iEndpointIndex);
1.667 + break;
1.668 +
1.669 + case ESetVerdictCase:
1.670 + iTestVerdict = ConvertToLocalVerdict(si.iEndpointIndex);
1.671 + break;
1.672 +
1.673 +
1.674 + /*
1.675 + * Debug cases
1.676 + */
1.677 +
1.678 + case EBreakPointCase:
1.679 + __BREAKPOINT();
1.680 + break;
1.681 +
1.682 + case ELogEnableCase:
1.683 + iLogging = ETrue;
1.684 + break;
1.685 +
1.686 + case EPanicCase:
1.687 + User::Panic(_L("EPanicCase"), -1);
1.688 + break;
1.689 +
1.690 + default:
1.691 + REMOTE_ERR_PRINTF2(_L("Invalid testcase %d"), aTestCase);
1.692 + User::Invariant();
1.693 + break;
1.694 + }
1.695 + }
1.696 +
1.697 +
1.698 +// Create thread that consumes some sort of resource (e.g. Heap or GPU memory)
1.699 +// @param aThreadNumber indicates "which"
1.700 +void CEgltest_Remote_Engine::StartThreadL(TInt aThreadNumber)
1.701 + {
1.702 + const TInt KStackSize = 12000;
1.703 + const TInt KHeapMinSize = 16000;
1.704 + const TInt KHeapMaxSize = 1000000;
1.705 +
1.706 + if (aThreadNumber >= KMaxLoadThreads)
1.707 + {
1.708 + User::Panic(_L("StartThreadL"), __LINE__);
1.709 + }
1.710 +
1.711 + __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], EFalse);
1.712 +
1.713 + TUint32 random = Math::Random();
1.714 + TName threadName;
1.715 + _LIT(KThreadNameFormat, "%S-%u");
1.716 +
1.717 + // Create a load-thread.
1.718 + _LIT(KThreadName, "EpTestLoadThread");
1.719 + threadName.Format(KThreadNameFormat, &KThreadName, random);
1.720 + TThreadFunction threadFunc = GetThreadFunction(aThreadNumber);
1.721 + if (threadFunc == NULL)
1.722 + {
1.723 + REMOTE_ERR_PRINTF2(_L("Requested thread function %d, got NULL pointer back!"), aThreadNumber);
1.724 + User::Leave(KErrArgument);
1.725 + }
1.726 + TInt err = iLoadThread[aThreadNumber].Create(threadName, threadFunc,
1.727 + KStackSize, KHeapMinSize, KHeapMaxSize, this, EOwnerThread);
1.728 + if(err != KErrNone)
1.729 + {
1.730 + REMOTE_ERR_PRINTF2(_L("Could not create load thread - err=%d"), err);
1.731 + User::Leave(err);
1.732 + }
1.733 + iLoadThread[aThreadNumber].Resume();
1.734 + }
1.735 +
1.736 +
1.737 +void CEgltest_Remote_Engine::EndThread(TInt aThreadNumber)
1.738 + {
1.739 + if (aThreadNumber >= KMaxLoadThreads)
1.740 + {
1.741 + User::Panic(_L("StartThreadL"), __LINE__);
1.742 + }
1.743 +
1.744 + TRequestStatus status;
1.745 + iLoadThread[aThreadNumber].Logon(status);
1.746 + // Tell thread to go away.
1.747 + __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], ETrue);
1.748 + User::WaitForRequest(status);
1.749 + iLoadThread[aThreadNumber].Close();
1.750 + }
1.751 +
1.752 +
1.753 +void CEgltest_Remote_Engine::CreateEndpointCaseL(const TRemoteTestParams &aParams, const TRemoteTestArgs& aArgs)
1.754 + {
1.755 + const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
1.756 + EGLDisplay dpy = aArgs.iDisplay;
1.757 + EGLEndpointNOK endpoint = aArgs.iEndpoint;
1.758 + const TSurfaceParamsRemote& cp = aParams.iEndpointEngine.iSurfaceParams;
1.759 +
1.760 + CEnumParams* endpointTypeParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadEndpointType),
1.761 + EGL_ENDPOINT_TYPE_CONSUMER_NOK);
1.762 + CEnumParams* sourceParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadSourceType),
1.763 + EGL_TSURFACEID_NOK);
1.764 + CSurfaceIdParams *surfParams = CSurfaceIdParams::NewLC(!!(si.iFlags & EUseBadSurfaceId),
1.765 + cp.iSurfaceId);
1.766 +
1.767 + TInt endpointTypeCount = endpointTypeParams->Count();
1.768 + TInt sourceCount = sourceParams->Count();
1.769 + TInt surfCount = surfParams->Count();
1.770 +
1.771 + for(TInt typeIter = 0; typeIter < endpointTypeCount; typeIter++)
1.772 + {
1.773 + EGLenum type = (*endpointTypeParams)[typeIter];
1.774 + for(TInt sourceIter = 0; sourceIter < sourceCount; sourceIter++)
1.775 + {
1.776 + EGLenum source_type = (*sourceParams)[sourceIter];
1.777 +
1.778 + for(TInt surfIter = 0; surfIter < surfCount; surfIter++)
1.779 + {
1.780 + EGLEndpointSourceNOK source = (EGLEndpointSourceNOK)(&(*surfParams)[surfIter]);
1.781 + EGLint *attrib_list = cp.iCommonParams.iUseAttribList?
1.782 + const_cast<EGLint *>(cp.iCommonParams.iAttribs):NULL;
1.783 +
1.784 + endpoint = EglEndpoint().CreateEndpoint(dpy, type, source_type, source, attrib_list);
1.785 + CHECK_RETURN_CAST(endpoint, EGL_NO_ENDPOINT_NOK, _S("eglCreateEndpoint"));
1.786 + if (endpoint != EGL_NO_ENDPOINT_NOK)
1.787 + {
1.788 + iEndpoints[si.iEndpointIndex] = endpoint;
1.789 + }
1.790 + }
1.791 + }
1.792 + }
1.793 + CleanupStack::PopAndDestroy(3);
1.794 + }
1.795 +
1.796 +
1.797 +void CEgltest_Remote_Engine::ReleaseImageCaseL(const TRemoteTestParams& aParams, const TRemoteTestArgs& aArgs)
1.798 + {
1.799 + const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
1.800 + EGLDisplay dpy = aArgs.iDisplay;
1.801 + EGLImageKHR image = aArgs.iImage;
1.802 + EGLEndpointNOK endpoint = aArgs.iEndpoint;
1.803 +
1.804 + static const EGLenum validAPIs[] = { EGL_OPENVG_API, EGL_OPENGL_API, EGL_OPENGL_ES_API };
1.805 + const TInt validAPIcount = sizeof(validAPIs) / sizeof(validAPIs[0]);
1.806 +
1.807 + CEnumParams* enumParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadApi),
1.808 + validAPIs, validAPIcount, 0);
1.809 + for(TInt enumIter = 0; enumIter < enumParams->Count(); enumIter++)
1.810 + {
1.811 + EGLenum api = (*enumParams)[enumIter];
1.812 + EGLBoolean ret = EglEndpoint().ReleaseImage(dpy, endpoint, image, api);
1.813 + CHECK_RETURN(ret, EGL_FALSE, _S("eglReleaseImage"));
1.814 + }
1.815 + CleanupStack::PopAndDestroy(enumParams);
1.816 + }
1.817 +
1.818 +void CEgltest_Remote_Engine::RequestNotificationL(const TRemoteTestParams& aParams, const TRemoteTestArgs &aArgs)
1.819 + {
1.820 + const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
1.821 + EGLDisplay dpy = aArgs.iDisplay;
1.822 + EGLEndpointNOK endpoint = aArgs.iEndpoint;
1.823 +
1.824 + CSyncParams* enumParams = CSyncParams::NewLC(!!(si.iFlags & EUseBadSync), &iRequestStatus[si.iEndpointIndex]);
1.825 + for(TInt enumIter = 0; enumIter < enumParams->Count(); enumIter++)
1.826 + {
1.827 + TRequestStatus* sync = (*enumParams)[enumIter];
1.828 + EGLBoolean ret = EglEndpoint().EndpointRequestNotification(dpy, endpoint, sync);
1.829 + CHECK_RETURN(ret, EGL_FALSE, _S("eglEndpointRequestNotification"));
1.830 + }
1.831 + CleanupStack::PopAndDestroy(enumParams);
1.832 + }
1.833 +
1.834 +// Mark either side of "rects" with something that we can detect.
1.835 +// Must not be a valid rect coordinate - which is unlikely for this
1.836 +// number (regardless of endianness), since it's roughly 0x40000000.
1.837 +static const EGLint KMarker = 'NTCH';
1.838 +// Allow space for this number of rectangles either side of the actual buffer.
1.839 +static const TInt KBufferArea = 2;
1.840 +
1.841 +void CEgltest_Remote_Engine::DoCheckRectsL(EGLint *aRectsBuffer, EGLint aRectCount, EGLint aMaxRects,
1.842 + TInt aRectsIndex, const TRect aSurfaceRect)
1.843 + {
1.844 + // Right now, this testing only supports "full surface" rectangles.
1.845 + ASSERT(aRectsIndex == 0);
1.846 + EGLint *rects = aRectsBuffer+KBufferArea * 4;
1.847 +
1.848 + // First, check the rects returned by the call. Should not be equal to KMarker.
1.849 + // For example, if we ask for 4 rects, and only two rects are filled in, index
1.850 + // 0 and 1 are checked that they are properly filled in.
1.851 + for (TInt i = 0; i < aRectCount * 4; i++)
1.852 + {
1.853 + if (rects[i] == KMarker)
1.854 + {
1.855 + iTestVerdict = ERtvFail;
1.856 + REMOTE_INFO_PRINTF3(_L("Seems the dirty area wasn't filled in properly! Got 0x%08x at %d"), rects[i], i);
1.857 + }
1.858 + }
1.859 + // Check the area not supposed to be filled in! All this should contain KMArker!
1.860 + // Check that the dirty area get call didn't fill in any memory
1.861 + // beyond the rectangles returned. Say we asked for 4 rectangles,
1.862 + // and two were returned, this will check that index 2 & 3 were
1.863 + // not modified. If we ask for 4 rects and get 4 rects back, nothing
1.864 + // is done here.
1.865 + for(TInt i = aRectCount * 4; i < aMaxRects * 4; i++)
1.866 + {
1.867 + if (rects[i] != KMarker)
1.868 + {
1.869 + iTestVerdict = ERtvFail;
1.870 + REMOTE_INFO_PRINTF3(_L("Seems the dirty area filled beyond the number of rects that it returned! Got 0x%08x at %d"), rects[i], i);
1.871 + }
1.872 + }
1.873 + // Check the "bufferaea" before the actual rects - MUST not be touched.
1.874 + for(TInt i = 0; i < KBufferArea * 4; i++)
1.875 + {
1.876 + if (aRectsBuffer[i] != KMarker)
1.877 + {
1.878 + iTestVerdict = ERtvFail;
1.879 + REMOTE_INFO_PRINTF3(_L("Seems the dirty area walked outside it's allowed memory! Got 0x%08x at %d"), rects[i], i);
1.880 + }
1.881 + }
1.882 + // Check the buffer area AFTER the buffer we gave - again, the
1.883 + // production code should ABSOLUTELY not write here.
1.884 + for(TInt i = (aMaxRects + KBufferArea) * 4; i < (aMaxRects + KBufferArea * 2) * 4; i++)
1.885 + {
1.886 + if (aRectsBuffer[i] != KMarker)
1.887 + {
1.888 + iTestVerdict = ERtvFail;
1.889 + REMOTE_INFO_PRINTF3(_L("Seems the dirty area walked outside it's allowed memory! Got 0x%08x at %d"), rects[i], i);
1.890 + }
1.891 + }
1.892 + if (aRectsIndex == 0)
1.893 + {
1.894 + // Check that rectangle matches the full surface extent.
1.895 + // We should only have ONE rectangle in this case!
1.896 + if (aRectCount != 1)
1.897 + {
1.898 + REMOTE_INFO_PRINTF2(_L("Expected 1 rectangle returned - got %d"), aRectCount);
1.899 + iTestVerdict = ERtvFail;
1.900 + }
1.901 + else
1.902 + {
1.903 + TRect returnedRect = TRect(rects[0], rects[1], rects[2], rects[3]);
1.904 + if (returnedRect != aSurfaceRect)
1.905 + {
1.906 + REMOTE_INFO_PRINTF1(_L("rectangles do not match!"));
1.907 + }
1.908 + }
1.909 + }
1.910 + // TODO: To support flexible sets of dirty area we need an else on the
1.911 + // above if-statement. However, with the current reference and the planned
1.912 + // third party known at this point, only "full surface" will ever be
1.913 + // returned.
1.914 + }
1.915 +
1.916 +void CEgltest_Remote_Engine::GetEndpointDirtyAreaL(const TRemoteTestParams& aParams, const TRemoteTestArgs& aArgs)
1.917 + {
1.918 + const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
1.919 + EGLDisplay dpy = aArgs.iDisplay;
1.920 + EGLEndpointNOK endpoint = aArgs.iEndpoint;
1.921 +
1.922 + EGLint *rects;
1.923 + EGLint *rectsBuffer = NULL;
1.924 + const TInt actualRectsSize = (si.iArg2 + KBufferArea * 2) * 4;
1.925 + // We don't use the "parameter expansion" for bad rects value.
1.926 + // This is because it's so easy to just add it here, and there is only one bad
1.927 + // value that is recognisable.
1.928 + if (si.iFlags & (EUseNullRects | EUseBadRects))
1.929 + {
1.930 + rects = NULL;
1.931 + }
1.932 + else
1.933 + {
1.934 + rectsBuffer = new EGLint[actualRectsSize];
1.935 + CleanupStack::PushL(rectsBuffer);
1.936 + rects = rectsBuffer + (KBufferArea * 4);
1.937 + for(TInt i = 0; i < actualRectsSize; i++)
1.938 + {
1.939 + rectsBuffer[i] = KMarker;
1.940 + }
1.941 + }
1.942 + EGLBoolean collapse = (si.iFlags & EUseCollapseArea)?EGL_TRUE:EGL_FALSE;
1.943 + EGLint ret = EglEndpoint().GetEndpointDirtyArea(dpy, endpoint, rects, si.iArg1, si.iArg2, collapse);
1.944 + if (!(si.iFlags & EExpectFailureMask))
1.945 + {
1.946 + if (rectsBuffer)
1.947 + {
1.948 + TInt rectsIndex = si.iImageIndex; // ImageIndex is used for rects!
1.949 + const TSurfaceParamsRemote &surfParams = aParams.iEndpointEngine.iSurfaceParams;
1.950 + // TODO: If the surface has been downscaled, we need to modify this rectangle.
1.951 + // We can only know if it's downsampled by getting the image, converting to a VGImage,
1.952 + // and getting the size of the VGImage. It can be done, but we would need to make
1.953 + // sure the imageindex matches the endpointindex, as imageindex is used by the
1.954 + // rectsindex (above).
1.955 + TRect surfaceRect = TRect(0, 0, surfParams.iCommonParams.iXSize-1, surfParams.iCommonParams.iYSize-1);
1.956 + DoCheckRectsL(rectsBuffer, ret, si.iArg2, rectsIndex, surfaceRect);
1.957 + }
1.958 + }
1.959 + if (rectsBuffer)
1.960 + {
1.961 + CleanupStack::PopAndDestroy(rectsBuffer);
1.962 + }
1.963 + if (ret != 0 || (si.iFlags & EExpectFailureMask))
1.964 + {
1.965 + CHECK_RETURN(ret, EGL_FALSE, _S("eglGetEndpointDirtyArea"));
1.966 + }
1.967 + }
1.968 +
1.969 +
1.970 +TInt CEgltest_Remote_Engine::LoadHeapMemory(TAny *aSelf)
1.971 + {
1.972 + CEgltest_Remote_Engine* self = reinterpret_cast<CEgltest_Remote_Engine*>(aSelf);
1.973 + User::SwitchHeap(self->iMainThreadHeap);
1.974 + CTrapCleanup *cleanUpStack = CTrapCleanup::New();
1.975 + if (!cleanUpStack)
1.976 + {
1.977 + // Can't use INFO_PRINTF here, as we have not yet
1.978 + // created the logger object - nor can we until we have
1.979 + // a working cleanupstack, so we just do our best at a
1.980 + // reasonable error message.
1.981 + RDebug::Printf("Could not allocate memory for cleanupStack!");
1.982 + User::Panic(_L("LoadThread"), __LINE__);
1.983 + return KErrNoMemory;
1.984 + }
1.985 +
1.986 + TRAPD(err, self->LoadHeapMemoryL());
1.987 + delete cleanUpStack;
1.988 + if (err != KErrNone)
1.989 + {
1.990 + RDebug::Printf("LoadThreadL left with %d", err);
1.991 + User::Panic(_L("LoadThread"), __LINE__);
1.992 + }
1.993 + return err;
1.994 + }
1.995 +
1.996 +
1.997 +void CEgltest_Remote_Engine::LoadHeapMemoryL()
1.998 + {
1.999 + const TInt KMaxAllocs = 40000;
1.1000 + char **ptr = new char*[KMaxAllocs];
1.1001 + TInt nAllocs = 0;
1.1002 + while(!__e32_atomic_load_acq32(&iStopThreadFlag[EThreadLoadHeapMemory]))
1.1003 + {
1.1004 + char *p = new char[1000];
1.1005 + if (p)
1.1006 + {
1.1007 + if (nAllocs >= KMaxAllocs)
1.1008 + {
1.1009 + User::Panic(_L("KMaxAllocs"), -3);
1.1010 + }
1.1011 + ptr[nAllocs++] = p;
1.1012 + }
1.1013 + else
1.1014 + {
1.1015 + RDebug::Printf("Memory full after %d allocations - freeing some", nAllocs);
1.1016 + // Now release 1/4 of the allocations...
1.1017 + TInt nRelease = nAllocs / 4;
1.1018 + for(int i = 0; i < nRelease; i++)
1.1019 + {
1.1020 + // Decrement first, then use as index.
1.1021 + delete [] ptr[--nAllocs];
1.1022 + }
1.1023 + User::After(10 * 1000); // Let others run for a bit
1.1024 + }
1.1025 + }
1.1026 + // Done - let's deallocate.
1.1027 + while(nAllocs)
1.1028 + {
1.1029 + delete [] ptr[--nAllocs];
1.1030 + }
1.1031 + delete [] ptr;
1.1032 + eglReleaseThread();
1.1033 + }
1.1034 +
1.1035 +
1.1036 +TInt CEgltest_Remote_Engine::LoadGpuMemory(TAny* aSelf)
1.1037 + {
1.1038 + CEgltest_Remote_Engine* self = reinterpret_cast<CEgltest_Remote_Engine*>(aSelf);
1.1039 + CTrapCleanup *cleanUpStack = CTrapCleanup::New();
1.1040 + if (!cleanUpStack)
1.1041 + {
1.1042 + // Can't use INFO_PRINTF here, as we have not yet
1.1043 + // created the logger object - nor can we until we have
1.1044 + // a working cleanupstack, so we just do our best at a
1.1045 + // reasonable error message.
1.1046 + RDebug::Printf("Could not allocate memory for cleanupStack!");
1.1047 + User::Panic(_L("LoadThread"), __LINE__);
1.1048 + return KErrNoMemory;
1.1049 + }
1.1050 +
1.1051 + TRAPD(err, self->LoadGpuMemoryL());
1.1052 + delete cleanUpStack;
1.1053 + if (err != KErrNone)
1.1054 + {
1.1055 + RDebug::Printf("LoadThreadL left with %d", err);
1.1056 + User::Panic(_L("LoadThread"), __LINE__);
1.1057 + }
1.1058 + return err;
1.1059 + }
1.1060 +
1.1061 +
1.1062 +void CEgltest_Remote_Engine::LoadGpuMemoryL()
1.1063 + {
1.1064 + const TInt KMaxSurfaceAllocs = 1000;
1.1065 + CSurface **surfaces = new CSurface*[KMaxSurfaceAllocs];
1.1066 + ENGINE_ASSERT(surfaces);
1.1067 + TInt nSurfaces = 0;
1.1068 + while(!__e32_atomic_load_acq32(&iStopThreadFlag[EThreadLoadGpuMemory]))
1.1069 + {
1.1070 + ENGINE_ASSERT(nSurfaces < KMaxSurfaceAllocs);
1.1071 + CSurface* s = CSurface::SurfaceFactoryL(ESurfTypePBuffer);
1.1072 + if (s)
1.1073 + {
1.1074 + TRAPD(err, s->CreateL(ELargeSurface));
1.1075 + if (err == KErrNone)
1.1076 + {
1.1077 + if (nSurfaces >= KMaxSurfaceAllocs)
1.1078 + {
1.1079 + User::Panic(_L("KMaxAllocs"), -3);
1.1080 + }
1.1081 + surfaces[nSurfaces++] = s;
1.1082 + s->DrawContentL(TRgb(0x10, 0x20, 0xB0));
1.1083 + }
1.1084 + else
1.1085 + {
1.1086 + delete s;
1.1087 + s = NULL;
1.1088 + }
1.1089 + }
1.1090 + if (!s)
1.1091 + {
1.1092 + User::After(100 * 1000);
1.1093 + TInt nRelease = nSurfaces / 4;
1.1094 + for(TInt i = 0; i < nRelease; i++)
1.1095 + {
1.1096 + delete surfaces[--nSurfaces];
1.1097 + surfaces[nSurfaces] = NULL;
1.1098 + }
1.1099 + User::After(100 * 1000); // 100 ms.
1.1100 + }
1.1101 + }
1.1102 + while(nSurfaces)
1.1103 + {
1.1104 + delete surfaces[--nSurfaces];
1.1105 + }
1.1106 + delete [] surfaces;
1.1107 + eglReleaseThread();
1.1108 + }
1.1109 +
1.1110 +
1.1111 +
1.1112 +TThreadFunction CEgltest_Remote_Engine::GetThreadFunction(TInt aThreadNumber)
1.1113 + {
1.1114 + switch(aThreadNumber)
1.1115 + {
1.1116 + case EThreadLoadHeapMemory:
1.1117 + return LoadHeapMemory;
1.1118 + case EThreadLoadGpuMemory:
1.1119 + return LoadGpuMemory;
1.1120 + }
1.1121 + RDebug::Printf("%s:%d: Unknown thread function %d", __FILE__, __LINE__, aThreadNumber);
1.1122 + return NULL;
1.1123 + }