os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_remote.cpp
Update contrib.
1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
19 @internalComponent - Internal Symbian test code
24 #include <e32atomics.h>
25 #include "egltest_endpoint_engine.h"
26 #include "egltest_endpoint_images.h"
27 #include "egltest_surface.h"
28 #include "egltest_parameters.h"
31 const TInt KMemStatsReserve = 3;
33 CEgltest_Remote_Engine::CEgltest_Remote_Engine()
34 : CRemoteTestStepBase(ETestUidEndpointEngine), iTestVerdict(ERtvPass), iLogging(EFalse), iSurface(0)
36 iMainThreadHeap = &User::Heap(); // ?? Is this the right heap ??
37 for (TInt i = 0; i < KMaxEndpoints; i++)
39 iEndpoints[i] = EGL_NO_ENDPOINT_NOK;
40 iEglImage[i] = EGL_NO_IMAGE_KHR;
42 iRequestStatus[i] = KRequestPending;
44 ipfnEglQueryProfilingDataNOK = reinterpret_cast<PFNEGLQUERYPROFILINGDATANOKPROC>(eglGetProcAddress("eglQueryProfilingDataNOK"));
45 if (ipfnEglQueryProfilingDataNOK)
47 RDebug::Printf("%s:%d: found eglQueryProfilingDataNOK function");
51 CEgltest_Remote_Engine::~CEgltest_Remote_Engine()
53 // Note: This is run from a different thread an on a different heap than the one
54 // used during the execution of DoRunRemoteTestCaseL(). So any allocation done
55 // during DoRunRemoteTestCaseL must be de-allocated in DoEndRemoteTestStepL()
58 TRemoteTestVerdict CEgltest_Remote_Engine::DoStartRemoteTestStepL(
59 const TRemoteTestParams& aParams)
61 iMainThreadHeap = &User::Heap();
63 iMemoryStats.ReserveL(KMemStatsReserve);
65 iLogErrors = aParams.iEndpointEngineConfig.iLogErrors;
69 TRemoteTestVerdict CEgltest_Remote_Engine::DoEndRemoteTestStepL(
70 const TRemoteTestParams& /* aParams */)
77 void CEgltest_Remote_Engine::CheckReturn(TInt aRetval,
78 const TEngineTestCase& aEngineTestCase, TInt aFailValue,
79 const TText* aFailSymbol, const TText* aFunction)
81 TBool isEqual = (aRetval == aFailValue);
82 TBool expectFail = (aEngineTestCase.iFlags & EExpectFailureMask) != 0;
84 EGLint err = eglGetError();
85 if (err != aEngineTestCase.iErrorExpected)
89 REMOTE_ERR_PRINTF3(_L("testcase failed: expected %04x, got %04x"), aEngineTestCase.iErrorExpected, err);
91 iTestVerdict = ERtvFail;
94 if (!isEqual && expectFail)
99 _L("return value when failing from %s is not expected fail value %s (%d). Value returned is %d"),
100 aFunction, aFailSymbol, aFailValue, aRetval);
102 iTestVerdict = ERtvFail;
104 else if (isEqual && !expectFail)
109 _L("return value when succeeding from %s is equal to expected fail value %s (%d). Value returned is %d"),
110 aFunction, aFailSymbol, aFailValue, aRetval);
112 iTestVerdict = ERtvFail;
114 if (isEqual != expectFail)
118 REMOTE_ERR_PRINTF4(_L("Unexpected result for %s, failvalue is %s, flags = %d"),
119 aFunction, aFailSymbol,
120 aEngineTestCase.iFlags);
122 iTestVerdict = ERtvFail;
125 if (expectFail && err == EGL_SUCCESS)
129 REMOTE_ERR_PRINTF2(_L("Got EGL_SUCCESS in error when calling %s, when we expected an error"),
132 iTestVerdict = ERtvFail;
134 // Didn't expect to fail, so we
135 else if (!expectFail && err != EGL_SUCCESS)
139 REMOTE_ERR_PRINTF3(_L("Got an error (%x) on successful call to %s, when expecting EGL_SUCCESS"),
142 iTestVerdict = ERtvFail;
146 #define CHECK_RETURN(retval, failval, func) \
147 CheckReturn((retval), si, (failval), _S(#failval), func)
149 #define CHECK_RETURN_CAST(retval, failval, func) \
150 CheckReturn(reinterpret_cast<int>(retval), si, reinterpret_cast<int>(failval), _S(#failval), func)
152 #define CHECK_BOOL_RET(func, funcName) \
154 EGLBoolean ret = EglEndpoint().func(dpy, endpoint); \
155 CheckReturn(ret, si, EGL_FALSE, _S("EGL_FALSE"), _S(funcName)); \
158 void CEgltest_Remote_Engine::LogDump(const TEngineTestCase& aCase)
160 const TText *caseName = EngineCaseName(aCase.iCase);
162 Log(((TText8*)__FILE__), __LINE__, ESevrInfo,
163 _L("Performing subcase %d (%s), with flags=%d, err=%04x endpointidx=%d, image=%d, args=(%d, %d)"),
167 aCase.iErrorExpected,
168 aCase.iEndpointIndex,
170 aCase.iArg1, aCase.iArg2);
173 TRemoteTestVerdict CEgltest_Remote_Engine::DoRunRemoteTestCaseL(
174 TInt aTestCase, const TRemoteTestParams &aParams)
176 TRemoteTestArgs args;
177 iTestVerdict = ERtvPass;
178 const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
180 CDisplayParams* displayParams = CDisplayParams::NewLC(!!(si.iFlags & EUseBadDisplay), eglGetDisplay(EGL_DEFAULT_DISPLAY));
181 TInt dpyParamsCount = displayParams->Count();
182 CEndpointParams* endpointParams = CEndpointParams::NewLC(!!(si.iFlags & EUseBadEndpoint), iEndpoints, KMaxEndpoints, si.iEndpointIndex);
183 TInt endpointCount = endpointParams->Count();
184 CImageParams* imageParams = CImageParams::NewLC(!!(si.iFlags & EUseBadEglImage), iEglImage, KMaxEndpoints, si.iImageIndex);
185 TInt imageCount = imageParams->Count();
187 for(TInt dpyIter = 0; dpyIter < dpyParamsCount; dpyIter++)
189 args.iDisplay = (*displayParams)[dpyIter];
190 for(TInt epIter = 0; epIter < endpointCount; epIter++)
192 args.iEndpoint = (*endpointParams)[epIter];
194 for(TInt imageIter = 0; imageIter < imageCount; imageIter++)
196 args.iImage = (*imageParams)[imageIter];
198 RunCaseL(aTestCase, aParams, args);
199 if (iLogErrors && iTestVerdict != ERtvPass || iLogging)
201 if (iTestVerdict != ERtvPass)
203 REMOTE_INFO_PRINTF1(_L("Test failed:"));
206 REMOTE_INFO_PRINTF4(_L("Using values: display: %d, endpoint: %d, image: %d"),
207 args.iDisplay, args.iEndpoint, args.iImage);
212 CleanupStack::PopAndDestroy(3);
217 void CEgltest_Remote_Engine::ActivateVgContextL()
221 iSurface = CEglWindowSurface::NewL();
222 iSurface->CreateL(EStandardSurface, TPoint(0, 110));
224 iSurface->ActivateL();
228 TInt CEgltest_Remote_Engine::FillGpuMemory()
230 TSurfaceIndex table[] =
233 EStandard128sqSurface,
237 const TInt KNumSurfaceTypes = sizeof(table) / sizeof(table[0]);
240 const TInt KMaxSurfaceAllocs = 1000;
241 CSurface **surfaces = new CSurface*[KMaxSurfaceAllocs];
243 ENGINE_ASSERT(surfaces);
244 for(TInt i = 0; i < KNumSurfaceTypes; i++)
247 while(err == KErrNone)
249 ENGINE_ASSERT(nSurfaces < KMaxSurfaceAllocs);
250 CSurface* s = CSurface::SurfaceFactoryL(ESurfTypePBuffer);
253 TRAP(err, s->CreateL(table[i]));
256 surfaces[nSurfaces++] = s;
257 // s->DrawContentL(TRgb(0x10, 0x20, 0xB0));
258 size += s->SizeInBytes();
263 RDebug::Printf("nSurfaces=%d", nSurfaces);
266 delete surfaces[--nSurfaces];
272 TInt CEgltest_Remote_Engine::CalculateAvailableGPUMemory()
275 if (ipfnEglQueryProfilingDataNOK)
277 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
278 ENGINE_ASSERT(display != EGL_NO_DISPLAY);
280 ipfnEglQueryProfilingDataNOK(
281 display, EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
283 ENGINE_ASSERT(count);
284 TInt *mem = new TInt[count * 2];
287 ipfnEglQueryProfilingDataNOK(
288 display, EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
289 mem, count, &newCount);
290 ENGINE_ASSERT(newCount == count);
291 for(TInt i = 0; i < count; i ++)
295 case EGL_PROF_USED_MEMORY_NOK:
296 // Assert that we only have one entry - if there are
297 // more than one, we can't really know what is the "right" one.
298 ENGINE_ASSERT(!result);
310 // This code currently causes a memory leak to be detected when the
311 // remote thread is destroyed. This causes further tests to be skipped.
312 // We disable this function at the moment, to allow other tests to run.
313 result = FillGpuMemory();
320 TInt CEgltest_Remote_Engine::CalculateAvailableHeapMemory()
323 return User::Heap().Available(biggest);
327 void CEgltest_Remote_Engine::CheckForMemoryLeaks()
329 TAvailableMemory mem;
330 mem.iGpuMemAvailable = CalculateAvailableGPUMemory();
331 mem.iHeapMemAvailable = CalculateAvailableHeapMemory();
333 REMOTE_INFO_PRINTF3(_L("GPU memory available: %d, heapmemory available: %d"),
334 mem.iGpuMemAvailable, mem.iHeapMemAvailable);
335 if (iMemoryStats.Count() == KMemStatsReserve)
337 REMOTE_INFO_PRINTF2(_L("false positive HEAP leak possible, as reserved memory is exhausted... (%d)"), KMemStatsReserve);
339 TInt err = iMemoryStats.Append(mem);
342 REMOTE_ERR_PRINTF2(_L("CheckForMemoryLeaks could not append to iMemoryStats. err=%d"), err);
346 void CEgltest_Remote_Engine::CheckForMemoryLeaksFinish()
348 TInt count = iMemoryStats.Count();
354 for(TInt i = 0; i < count; i++)
356 sumGpu += iMemoryStats[i].iGpuMemAvailable;
357 sumHeap += iMemoryStats[i].iHeapMemAvailable;
359 REMOTE_INFO_PRINTF2(_L("CheckMemoryLeaksFinish - average = %6.2f"), sumGpu / count);
360 REMOTE_INFO_PRINTF2(_L("CheckMemoryLeaksFinish - average = %6.2f"), sumHeap / count);
364 REMOTE_INFO_PRINTF1(_L("CheckMemoryLeaksFinish - no data collected"));
366 iMemoryStats.Close();
369 TRemoteTestVerdict ConvertToLocalVerdict(TInt aVerdict)
378 return ERtvInconclusive;
381 void CEgltest_Remote_Engine::RunCaseL(TInt aTestCase, const TRemoteTestParams &aParams, const TRemoteTestArgs& aArgs)
383 const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
384 EGLDisplay dpy = aArgs.iDisplay;
385 EGLImageKHR image = aArgs.iImage;
386 EGLEndpointNOK endpoint = aArgs.iEndpoint;
390 case EInitializeCase:
391 REMOTE_INFO_PRINTF1(_L("calling EglStartL()"));
395 case ECreateEndpointCase:
396 CreateEndpointCaseL(aParams, aArgs);
399 case EAcquireImageCase:
400 image = EglEndpoint().AcquireImage(dpy, endpoint);
401 CHECK_RETURN(image, EGL_NO_IMAGE_KHR, _S("eglAcquireImage"));
402 if (image != EGL_NO_IMAGE_KHR)
404 iEglImage[si.iEndpointIndex] = image;
408 case ECompareImageCase:
409 if (iEglImage[si.iEndpointIndex] == EGL_NO_IMAGE_KHR)
411 REMOTE_ERR_PRINTF2(_L("Image at index %d is not a valid eglImage"), si.iEndpointIndex);
412 iTestVerdict = ERtvFail;
416 ActivateVgContextL();
418 CTestCFbsImage *image = CTestCFbsImage::NewL(si.iImageIndex);
419 CleanupStack::PushL(image);
420 CTestVgEglImage *vgImage = CTestVgEglImage::New(iEglImage[si.iEndpointIndex]);
423 REMOTE_INFO_PRINTF2(_L("Could not create vgimage from eglimage: endpointindex=%d"),
428 CleanupStack::PushL(vgImage);
429 TBool res = vgImage->CompareImageL(image, !!(si.iFlags & EExpectError));
430 if (res != !(si.iFlags & EExpectError))
434 REMOTE_ERR_PRINTF1(_L("Pixel comparison failed...."));
436 iTestVerdict = ERtvFail;
438 else if (!(si.iFlags & EExpectError))
440 // Extra check that ANOTHER image doesn't match the image
442 // This would detect when images have incorrect content or
443 // the code for comparing images have been broken.
444 TInt imageIndex2 = (si.iImageIndex + 1) % CTestImage::KImageCount;
445 CTestCFbsImage *image2 = CTestCFbsImage::NewL(imageIndex2);
446 CleanupStack::PushL(image2);
447 res = vgImage->CompareImageL(image2, ETrue);
450 REMOTE_ERR_PRINTF1(_L("Pixel comparison didn't fail - two images the same?...."));
451 iTestVerdict = ERtvFail;
453 CleanupStack::PopAndDestroy(image2);
455 CleanupStack::PopAndDestroy(vgImage);
457 CleanupStack::PopAndDestroy(image);
461 case EReleaseImageCase:
462 ReleaseImageCaseL(aParams, aArgs);
465 case EBeginStreamingCase:
466 CHECK_BOOL_RET(EndpointBeginStreaming, "eglEndpointBeginStreaming");
469 case EEndStreamingCase:
470 CHECK_BOOL_RET(EndpointEndStreaming, "eglEndpointEndStreaming");
473 case EDestroyEndpointCase:
474 CHECK_BOOL_RET(DestroyEndpoint, "eglDestroyEndpoint");
479 TInt value = EglEndpoint().GetEndpointAttrib(dpy, endpoint, si.iArg1);
480 // We can't use the macro CHECK_RETURN here, as the return value for
481 // "success" can be any integer value, including "EGL_FALSE". So we can
482 // only check when we expect failure.
483 if (si.iFlags & EExpectFailureMask)
485 CheckReturn(value, si, EGL_FALSE,_S("EGL_FALSE") ,_S("eglGetEndpointAttrib"));
489 EGLint err = eglGetError();
490 if (err != EGL_SUCCESS)
492 REMOTE_ERR_PRINTF2(_L("Got an error (%x) on successful call to eglGetEndpointAttrib, when expecting EGL_SUCCESS in error"),
494 iTestVerdict = ERtvFail;
497 if (value != si.iArg2)
499 REMOTE_ERR_PRINTF4(_L("GetEndpointAttrib(%04x), got %d, expected %d"), si.iArg1, value, si.iArg2);
500 iTestVerdict = ERtvFail;
507 EGLBoolean ret = EglEndpoint().SetEndpointAttrib(dpy, endpoint, si.iArg1, si.iArg2);
508 CHECK_RETURN(ret, EGL_FALSE, _S("eglSetEndpointAttrib"));
512 case EDestroyEglImageCase:
514 EGLBoolean ret = EglEndpoint().DestroyImage(dpy, image);
515 CHECK_RETURN(ret, EGL_FALSE, _S("eglDestroyImageKHR"));
519 case ECreateVgImageCase:
521 // For a VgImage to be possible to create, we need to have a EglSurface.
522 ActivateVgContextL();
524 TRAPD(err, iVgImage[si.iImageIndex] = CTestVgEglImage::NewL(iEglImage[si.iEndpointIndex]));
525 if ((si.iFlags & EExpectFailureMask) && err == KErrNone)
527 REMOTE_ERR_PRINTF1(_L("Successfully created VGImage when we expected an error"));
528 iTestVerdict = ERtvFail;
529 delete iVgImage[si.iImageIndex];
530 iVgImage[si.iImageIndex] = NULL;
532 else if (!(si.iFlags & EExpectFailureMask) && err != KErrNone)
534 REMOTE_ERR_PRINTF1(_L("Failed to create VGImage when we expected to succeed"));
535 iTestVerdict = ERtvFail;
540 // Test that a vgImage can be used. We do NOT test the content for anything in particular, since
541 // the current usage of this is to do checking on a vgImage after endpoint is destroyed, and the
542 // specification is that the vgImage is undefined under this condition.
543 case ETestVgImageValidCase:
545 ActivateVgContextL();
546 CTestVgEglImage *vgImage = iVgImage[si.iImageIndex];
550 REMOTE_ERR_PRINTF1(_L("VGImage is not present"));
551 iTestVerdict = ERtvFail;
555 vgDrawImage(vgImage->VGImage());
556 VGint err = vgGetError();
557 if (err != VG_NO_ERROR)
559 iTestVerdict = ERtvFail;
562 TSize size = vgImage->Size();
563 // Now read the pixels in four corners and the middle to check if the image is still "working".
564 vgImage->Pixel(0, 0);
565 vgImage->Pixel(size.iWidth-1, size.iHeight-1);
566 vgImage->Pixel(0, size.iHeight-1);
567 vgImage->Pixel(size.iWidth-1, 0);
568 vgImage->Pixel(size.iWidth >> 1, size.iHeight >> 1);
571 // If we get here, the image is "working" - we expect to panic or crash if it's not...
575 case EDestroyVgImageCase:
576 delete iVgImage[si.iImageIndex];
577 iVgImage[si.iImageIndex] = NULL;
580 case ERequestNotificationCase:
581 RequestNotificationL(aParams, aArgs);
584 case ECancelNotificationCase:
585 CHECK_BOOL_RET(EndpointCancelNotification, "eglEndpointCancelNotification");
588 case EWaitForNotificationCase:
591 TInt err = timer.CreateLocal();
594 REMOTE_INFO_PRINTF2(_L("Could not create timer. Error=%d"), err);
595 iTestVerdict = ERtvFail;
599 TRequestStatus timerStatus = KRequestPending;
600 timer.HighRes(timerStatus, si.iArg1);
601 // Note that the requeststatus is set to KRequestPending by
602 // eglEndpointRequestNotificationNOK(), so we don't do that
603 // before waiting. See below for more comments.
604 TRequestStatus *requestStatus = &iRequestStatus[si.iEndpointIndex];
605 User::WaitForRequest(timerStatus, *requestStatus);
606 TInt result = KErrNotReady; // Give it some ERROR value that is unlikely to happen later.
609 if (timerStatus == KErrNone && *requestStatus == KRequestPending)
611 result = KErrTimedOut;
615 result = requestStatus->Int();
617 // Reset the request - this allows us to (ab-)use this request to
618 // wait for things that aren't completing, etc.
619 *requestStatus = KRequestPending;
620 if ((si.iFlags & EExpectError) && result >= KErrNone)
622 iTestVerdict = ERtvFail;
623 REMOTE_INFO_PRINTF1(_L("Expected failure, but result was a success"));
625 else if (!(si.iFlags & EExpectError) && result < KErrNone)
627 iTestVerdict = ERtvFail;
628 REMOTE_INFO_PRINTF1(_L("Expected success, but result was a failure"));
630 if (result != si.iErrorExpected)
632 iTestVerdict = ERtvFail;
633 REMOTE_INFO_PRINTF3(_L("EWaitForNotificationCase: Expected error %d, got %d"), si.iErrorExpected, result);
639 case EGetEndpointDirtyAreaCase:
640 GetEndpointDirtyAreaL(aParams, aArgs);
644 REMOTE_INFO_PRINTF1(_L("calling EglEndL()"));
648 // Memory leak checking functions.
649 case ECheckForMemoryLeaks:
650 CheckForMemoryLeaks();
653 case ECheckForMemoryLeaksFinish:
654 CheckForMemoryLeaksFinish();
658 case EStartLoadThreadCase:
659 StartThreadL(si.iEndpointIndex);
662 case EEndLoadThreadCase:
663 EndThread(si.iEndpointIndex);
666 case ESetVerdictCase:
667 iTestVerdict = ConvertToLocalVerdict(si.iEndpointIndex);
675 case EBreakPointCase:
684 User::Panic(_L("EPanicCase"), -1);
688 REMOTE_ERR_PRINTF2(_L("Invalid testcase %d"), aTestCase);
695 // Create thread that consumes some sort of resource (e.g. Heap or GPU memory)
696 // @param aThreadNumber indicates "which"
697 void CEgltest_Remote_Engine::StartThreadL(TInt aThreadNumber)
699 const TInt KStackSize = 12000;
700 const TInt KHeapMinSize = 16000;
701 const TInt KHeapMaxSize = 1000000;
703 if (aThreadNumber >= KMaxLoadThreads)
705 User::Panic(_L("StartThreadL"), __LINE__);
708 __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], EFalse);
710 TUint32 random = Math::Random();
712 _LIT(KThreadNameFormat, "%S-%u");
714 // Create a load-thread.
715 _LIT(KThreadName, "EpTestLoadThread");
716 threadName.Format(KThreadNameFormat, &KThreadName, random);
717 TThreadFunction threadFunc = GetThreadFunction(aThreadNumber);
718 if (threadFunc == NULL)
720 REMOTE_ERR_PRINTF2(_L("Requested thread function %d, got NULL pointer back!"), aThreadNumber);
721 User::Leave(KErrArgument);
723 TInt err = iLoadThread[aThreadNumber].Create(threadName, threadFunc,
724 KStackSize, KHeapMinSize, KHeapMaxSize, this, EOwnerThread);
727 REMOTE_ERR_PRINTF2(_L("Could not create load thread - err=%d"), err);
730 iLoadThread[aThreadNumber].Resume();
734 void CEgltest_Remote_Engine::EndThread(TInt aThreadNumber)
736 if (aThreadNumber >= KMaxLoadThreads)
738 User::Panic(_L("StartThreadL"), __LINE__);
741 TRequestStatus status;
742 iLoadThread[aThreadNumber].Logon(status);
743 // Tell thread to go away.
744 __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], ETrue);
745 User::WaitForRequest(status);
746 iLoadThread[aThreadNumber].Close();
750 void CEgltest_Remote_Engine::CreateEndpointCaseL(const TRemoteTestParams &aParams, const TRemoteTestArgs& aArgs)
752 const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
753 EGLDisplay dpy = aArgs.iDisplay;
754 EGLEndpointNOK endpoint = aArgs.iEndpoint;
755 const TSurfaceParamsRemote& cp = aParams.iEndpointEngine.iSurfaceParams;
757 CEnumParams* endpointTypeParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadEndpointType),
758 EGL_ENDPOINT_TYPE_CONSUMER_NOK);
759 CEnumParams* sourceParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadSourceType),
761 CSurfaceIdParams *surfParams = CSurfaceIdParams::NewLC(!!(si.iFlags & EUseBadSurfaceId),
764 TInt endpointTypeCount = endpointTypeParams->Count();
765 TInt sourceCount = sourceParams->Count();
766 TInt surfCount = surfParams->Count();
768 for(TInt typeIter = 0; typeIter < endpointTypeCount; typeIter++)
770 EGLenum type = (*endpointTypeParams)[typeIter];
771 for(TInt sourceIter = 0; sourceIter < sourceCount; sourceIter++)
773 EGLenum source_type = (*sourceParams)[sourceIter];
775 for(TInt surfIter = 0; surfIter < surfCount; surfIter++)
777 EGLEndpointSourceNOK source = (EGLEndpointSourceNOK)(&(*surfParams)[surfIter]);
778 EGLint *attrib_list = cp.iCommonParams.iUseAttribList?
779 const_cast<EGLint *>(cp.iCommonParams.iAttribs):NULL;
781 endpoint = EglEndpoint().CreateEndpoint(dpy, type, source_type, source, attrib_list);
782 CHECK_RETURN_CAST(endpoint, EGL_NO_ENDPOINT_NOK, _S("eglCreateEndpoint"));
783 if (endpoint != EGL_NO_ENDPOINT_NOK)
785 iEndpoints[si.iEndpointIndex] = endpoint;
790 CleanupStack::PopAndDestroy(3);
794 void CEgltest_Remote_Engine::ReleaseImageCaseL(const TRemoteTestParams& aParams, const TRemoteTestArgs& aArgs)
796 const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
797 EGLDisplay dpy = aArgs.iDisplay;
798 EGLImageKHR image = aArgs.iImage;
799 EGLEndpointNOK endpoint = aArgs.iEndpoint;
801 static const EGLenum validAPIs[] = { EGL_OPENVG_API, EGL_OPENGL_API, EGL_OPENGL_ES_API };
802 const TInt validAPIcount = sizeof(validAPIs) / sizeof(validAPIs[0]);
804 CEnumParams* enumParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadApi),
805 validAPIs, validAPIcount, 0);
806 for(TInt enumIter = 0; enumIter < enumParams->Count(); enumIter++)
808 EGLenum api = (*enumParams)[enumIter];
809 EGLBoolean ret = EglEndpoint().ReleaseImage(dpy, endpoint, image, api);
810 CHECK_RETURN(ret, EGL_FALSE, _S("eglReleaseImage"));
812 CleanupStack::PopAndDestroy(enumParams);
815 void CEgltest_Remote_Engine::RequestNotificationL(const TRemoteTestParams& aParams, const TRemoteTestArgs &aArgs)
817 const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
818 EGLDisplay dpy = aArgs.iDisplay;
819 EGLEndpointNOK endpoint = aArgs.iEndpoint;
821 CSyncParams* enumParams = CSyncParams::NewLC(!!(si.iFlags & EUseBadSync), &iRequestStatus[si.iEndpointIndex]);
822 for(TInt enumIter = 0; enumIter < enumParams->Count(); enumIter++)
824 TRequestStatus* sync = (*enumParams)[enumIter];
825 EGLBoolean ret = EglEndpoint().EndpointRequestNotification(dpy, endpoint, sync);
826 CHECK_RETURN(ret, EGL_FALSE, _S("eglEndpointRequestNotification"));
828 CleanupStack::PopAndDestroy(enumParams);
831 // Mark either side of "rects" with something that we can detect.
832 // Must not be a valid rect coordinate - which is unlikely for this
833 // number (regardless of endianness), since it's roughly 0x40000000.
834 static const EGLint KMarker = 'NTCH';
835 // Allow space for this number of rectangles either side of the actual buffer.
836 static const TInt KBufferArea = 2;
838 void CEgltest_Remote_Engine::DoCheckRectsL(EGLint *aRectsBuffer, EGLint aRectCount, EGLint aMaxRects,
839 TInt aRectsIndex, const TRect aSurfaceRect)
841 // Right now, this testing only supports "full surface" rectangles.
842 ASSERT(aRectsIndex == 0);
843 EGLint *rects = aRectsBuffer+KBufferArea * 4;
845 // First, check the rects returned by the call. Should not be equal to KMarker.
846 // For example, if we ask for 4 rects, and only two rects are filled in, index
847 // 0 and 1 are checked that they are properly filled in.
848 for (TInt i = 0; i < aRectCount * 4; i++)
850 if (rects[i] == KMarker)
852 iTestVerdict = ERtvFail;
853 REMOTE_INFO_PRINTF3(_L("Seems the dirty area wasn't filled in properly! Got 0x%08x at %d"), rects[i], i);
856 // Check the area not supposed to be filled in! All this should contain KMArker!
857 // Check that the dirty area get call didn't fill in any memory
858 // beyond the rectangles returned. Say we asked for 4 rectangles,
859 // and two were returned, this will check that index 2 & 3 were
860 // not modified. If we ask for 4 rects and get 4 rects back, nothing
862 for(TInt i = aRectCount * 4; i < aMaxRects * 4; i++)
864 if (rects[i] != KMarker)
866 iTestVerdict = ERtvFail;
867 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);
870 // Check the "bufferaea" before the actual rects - MUST not be touched.
871 for(TInt i = 0; i < KBufferArea * 4; i++)
873 if (aRectsBuffer[i] != KMarker)
875 iTestVerdict = ERtvFail;
876 REMOTE_INFO_PRINTF3(_L("Seems the dirty area walked outside it's allowed memory! Got 0x%08x at %d"), rects[i], i);
879 // Check the buffer area AFTER the buffer we gave - again, the
880 // production code should ABSOLUTELY not write here.
881 for(TInt i = (aMaxRects + KBufferArea) * 4; i < (aMaxRects + KBufferArea * 2) * 4; i++)
883 if (aRectsBuffer[i] != KMarker)
885 iTestVerdict = ERtvFail;
886 REMOTE_INFO_PRINTF3(_L("Seems the dirty area walked outside it's allowed memory! Got 0x%08x at %d"), rects[i], i);
889 if (aRectsIndex == 0)
891 // Check that rectangle matches the full surface extent.
892 // We should only have ONE rectangle in this case!
895 REMOTE_INFO_PRINTF2(_L("Expected 1 rectangle returned - got %d"), aRectCount);
896 iTestVerdict = ERtvFail;
900 TRect returnedRect = TRect(rects[0], rects[1], rects[2], rects[3]);
901 if (returnedRect != aSurfaceRect)
903 REMOTE_INFO_PRINTF1(_L("rectangles do not match!"));
907 // TODO: To support flexible sets of dirty area we need an else on the
908 // above if-statement. However, with the current reference and the planned
909 // third party known at this point, only "full surface" will ever be
913 void CEgltest_Remote_Engine::GetEndpointDirtyAreaL(const TRemoteTestParams& aParams, const TRemoteTestArgs& aArgs)
915 const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
916 EGLDisplay dpy = aArgs.iDisplay;
917 EGLEndpointNOK endpoint = aArgs.iEndpoint;
920 EGLint *rectsBuffer = NULL;
921 const TInt actualRectsSize = (si.iArg2 + KBufferArea * 2) * 4;
922 // We don't use the "parameter expansion" for bad rects value.
923 // This is because it's so easy to just add it here, and there is only one bad
924 // value that is recognisable.
925 if (si.iFlags & (EUseNullRects | EUseBadRects))
931 rectsBuffer = new EGLint[actualRectsSize];
932 CleanupStack::PushL(rectsBuffer);
933 rects = rectsBuffer + (KBufferArea * 4);
934 for(TInt i = 0; i < actualRectsSize; i++)
936 rectsBuffer[i] = KMarker;
939 EGLBoolean collapse = (si.iFlags & EUseCollapseArea)?EGL_TRUE:EGL_FALSE;
940 EGLint ret = EglEndpoint().GetEndpointDirtyArea(dpy, endpoint, rects, si.iArg1, si.iArg2, collapse);
941 if (!(si.iFlags & EExpectFailureMask))
945 TInt rectsIndex = si.iImageIndex; // ImageIndex is used for rects!
946 const TSurfaceParamsRemote &surfParams = aParams.iEndpointEngine.iSurfaceParams;
947 // TODO: If the surface has been downscaled, we need to modify this rectangle.
948 // We can only know if it's downsampled by getting the image, converting to a VGImage,
949 // and getting the size of the VGImage. It can be done, but we would need to make
950 // sure the imageindex matches the endpointindex, as imageindex is used by the
951 // rectsindex (above).
952 TRect surfaceRect = TRect(0, 0, surfParams.iCommonParams.iXSize-1, surfParams.iCommonParams.iYSize-1);
953 DoCheckRectsL(rectsBuffer, ret, si.iArg2, rectsIndex, surfaceRect);
958 CleanupStack::PopAndDestroy(rectsBuffer);
960 if (ret != 0 || (si.iFlags & EExpectFailureMask))
962 CHECK_RETURN(ret, EGL_FALSE, _S("eglGetEndpointDirtyArea"));
967 TInt CEgltest_Remote_Engine::LoadHeapMemory(TAny *aSelf)
969 CEgltest_Remote_Engine* self = reinterpret_cast<CEgltest_Remote_Engine*>(aSelf);
970 User::SwitchHeap(self->iMainThreadHeap);
971 CTrapCleanup *cleanUpStack = CTrapCleanup::New();
974 // Can't use INFO_PRINTF here, as we have not yet
975 // created the logger object - nor can we until we have
976 // a working cleanupstack, so we just do our best at a
977 // reasonable error message.
978 RDebug::Printf("Could not allocate memory for cleanupStack!");
979 User::Panic(_L("LoadThread"), __LINE__);
983 TRAPD(err, self->LoadHeapMemoryL());
987 RDebug::Printf("LoadThreadL left with %d", err);
988 User::Panic(_L("LoadThread"), __LINE__);
994 void CEgltest_Remote_Engine::LoadHeapMemoryL()
996 const TInt KMaxAllocs = 40000;
997 char **ptr = new char*[KMaxAllocs];
999 while(!__e32_atomic_load_acq32(&iStopThreadFlag[EThreadLoadHeapMemory]))
1001 char *p = new char[1000];
1004 if (nAllocs >= KMaxAllocs)
1006 User::Panic(_L("KMaxAllocs"), -3);
1012 RDebug::Printf("Memory full after %d allocations - freeing some", nAllocs);
1013 // Now release 1/4 of the allocations...
1014 TInt nRelease = nAllocs / 4;
1015 for(int i = 0; i < nRelease; i++)
1017 // Decrement first, then use as index.
1018 delete [] ptr[--nAllocs];
1020 User::After(10 * 1000); // Let others run for a bit
1023 // Done - let's deallocate.
1026 delete [] ptr[--nAllocs];
1033 TInt CEgltest_Remote_Engine::LoadGpuMemory(TAny* aSelf)
1035 CEgltest_Remote_Engine* self = reinterpret_cast<CEgltest_Remote_Engine*>(aSelf);
1036 CTrapCleanup *cleanUpStack = CTrapCleanup::New();
1039 // Can't use INFO_PRINTF here, as we have not yet
1040 // created the logger object - nor can we until we have
1041 // a working cleanupstack, so we just do our best at a
1042 // reasonable error message.
1043 RDebug::Printf("Could not allocate memory for cleanupStack!");
1044 User::Panic(_L("LoadThread"), __LINE__);
1045 return KErrNoMemory;
1048 TRAPD(err, self->LoadGpuMemoryL());
1049 delete cleanUpStack;
1050 if (err != KErrNone)
1052 RDebug::Printf("LoadThreadL left with %d", err);
1053 User::Panic(_L("LoadThread"), __LINE__);
1059 void CEgltest_Remote_Engine::LoadGpuMemoryL()
1061 const TInt KMaxSurfaceAllocs = 1000;
1062 CSurface **surfaces = new CSurface*[KMaxSurfaceAllocs];
1063 ENGINE_ASSERT(surfaces);
1065 while(!__e32_atomic_load_acq32(&iStopThreadFlag[EThreadLoadGpuMemory]))
1067 ENGINE_ASSERT(nSurfaces < KMaxSurfaceAllocs);
1068 CSurface* s = CSurface::SurfaceFactoryL(ESurfTypePBuffer);
1071 TRAPD(err, s->CreateL(ELargeSurface));
1072 if (err == KErrNone)
1074 if (nSurfaces >= KMaxSurfaceAllocs)
1076 User::Panic(_L("KMaxAllocs"), -3);
1078 surfaces[nSurfaces++] = s;
1079 s->DrawContentL(TRgb(0x10, 0x20, 0xB0));
1089 User::After(100 * 1000);
1090 TInt nRelease = nSurfaces / 4;
1091 for(TInt i = 0; i < nRelease; i++)
1093 delete surfaces[--nSurfaces];
1094 surfaces[nSurfaces] = NULL;
1096 User::After(100 * 1000); // 100 ms.
1101 delete surfaces[--nSurfaces];
1109 TThreadFunction CEgltest_Remote_Engine::GetThreadFunction(TInt aThreadNumber)
1111 switch(aThreadNumber)
1113 case EThreadLoadHeapMemory:
1114 return LoadHeapMemory;
1115 case EThreadLoadGpuMemory:
1116 return LoadGpuMemory;
1118 RDebug::Printf("%s:%d: Unknown thread function %d", __FILE__, __LINE__, aThreadNumber);