os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_remote.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 /**
    17  @file
    18  @test
    19  @internalComponent - Internal Symbian test code
    20 */
    21 
    22 #include <e32std.h>
    23 #include <e32math.h>
    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"
    29 
    30 
    31 const TInt KMemStatsReserve = 3;
    32 
    33 CEgltest_Remote_Engine::CEgltest_Remote_Engine()
    34     : CRemoteTestStepBase(ETestUidEndpointEngine), iTestVerdict(ERtvPass), iLogging(EFalse), iSurface(0)
    35     {
    36     iMainThreadHeap = &User::Heap();   // ?? Is this the right heap ??
    37     for (TInt i = 0; i < KMaxEndpoints; i++)
    38         {
    39         iEndpoints[i] = EGL_NO_ENDPOINT_NOK;
    40         iEglImage[i] = EGL_NO_IMAGE_KHR;
    41         iVgImage[i] = NULL;
    42         iRequestStatus[i] = KRequestPending;
    43         }
    44     ipfnEglQueryProfilingDataNOK = reinterpret_cast<PFNEGLQUERYPROFILINGDATANOKPROC>(eglGetProcAddress("eglQueryProfilingDataNOK"));
    45     if (ipfnEglQueryProfilingDataNOK)
    46         {
    47         RDebug::Printf("%s:%d: found eglQueryProfilingDataNOK function");
    48         }
    49     }
    50 
    51 CEgltest_Remote_Engine::~CEgltest_Remote_Engine()
    52     {
    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()
    56     }
    57 
    58 TRemoteTestVerdict CEgltest_Remote_Engine::DoStartRemoteTestStepL(
    59         const TRemoteTestParams& aParams)
    60     {
    61     iMainThreadHeap = &User::Heap();   
    62     
    63     iMemoryStats.ReserveL(KMemStatsReserve);
    64     iLogging = EFalse;
    65     iLogErrors = aParams.iEndpointEngineConfig.iLogErrors;
    66     return ERtvPass;
    67     }
    68 
    69 TRemoteTestVerdict CEgltest_Remote_Engine::DoEndRemoteTestStepL(
    70         const TRemoteTestParams& /* aParams */)
    71     {
    72     iMemoryStats.Close();
    73     delete iSurface;
    74     return ERtvPass;
    75     }
    76 
    77 void CEgltest_Remote_Engine::CheckReturn(TInt aRetval,
    78         const TEngineTestCase& aEngineTestCase, TInt aFailValue,
    79         const TText* aFailSymbol, const TText* aFunction)
    80     {
    81     TBool isEqual = (aRetval == aFailValue);
    82     TBool expectFail = (aEngineTestCase.iFlags & EExpectFailureMask) != 0;
    83 
    84     EGLint err = eglGetError();
    85     if (err != aEngineTestCase.iErrorExpected)
    86         {
    87         if (iLogErrors)
    88             {
    89             REMOTE_ERR_PRINTF3(_L("testcase failed: expected %04x, got %04x"), aEngineTestCase.iErrorExpected, err);
    90             }
    91         iTestVerdict = ERtvFail;
    92         }
    93 
    94     if (!isEqual && expectFail)
    95         {
    96         if (iLogErrors)
    97             {
    98             REMOTE_ERR_PRINTF5(
    99                     _L("return value when failing from %s is not expected fail value %s (%d). Value returned is %d"),
   100                     aFunction, aFailSymbol, aFailValue, aRetval);
   101             }
   102         iTestVerdict = ERtvFail;
   103         }
   104     else if (isEqual && !expectFail)
   105         {
   106         if (iLogErrors)
   107             {
   108             REMOTE_ERR_PRINTF5(
   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);
   111             }
   112         iTestVerdict = ERtvFail;
   113         }
   114     if (isEqual != expectFail)
   115         {
   116         if (iLogErrors)
   117             {
   118             REMOTE_ERR_PRINTF4(_L("Unexpected result for %s, failvalue is %s, flags = %d"),
   119                     aFunction, aFailSymbol,
   120                     aEngineTestCase.iFlags);
   121             }
   122         iTestVerdict = ERtvFail;
   123         }
   124     // Now check
   125     if (expectFail && err == EGL_SUCCESS)
   126         {
   127         if (iLogErrors)
   128             {
   129             REMOTE_ERR_PRINTF2(_L("Got EGL_SUCCESS in error when calling %s, when we expected an error"),
   130                     aFunction);
   131             }
   132         iTestVerdict = ERtvFail;
   133         }
   134     // Didn't expect to fail, so we
   135     else if (!expectFail && err != EGL_SUCCESS)
   136         {
   137         if (iLogErrors)
   138             {
   139             REMOTE_ERR_PRINTF3(_L("Got an error (%x) on successful call to %s, when expecting EGL_SUCCESS"),
   140                     err, aFunction);
   141             }
   142         iTestVerdict = ERtvFail;
   143         }
   144     }
   145 
   146 #define CHECK_RETURN(retval, failval, func) \
   147     CheckReturn((retval), si, (failval), _S(#failval), func)
   148 
   149 #define CHECK_RETURN_CAST(retval, failval, func) \
   150     CheckReturn(reinterpret_cast<int>(retval), si, reinterpret_cast<int>(failval), _S(#failval), func)
   151 
   152 #define CHECK_BOOL_RET(func, funcName) \
   153 {  \
   154     EGLBoolean ret = EglEndpoint().func(dpy, endpoint);     \
   155     CheckReturn(ret, si, EGL_FALSE, _S("EGL_FALSE"), _S(funcName));  \
   156 }
   157 
   158 void CEgltest_Remote_Engine::LogDump(const TEngineTestCase& aCase)
   159     {
   160     const TText *caseName = EngineCaseName(aCase.iCase);
   161 
   162     Log(((TText8*)__FILE__), __LINE__, ESevrInfo,
   163                     _L("Performing subcase %d (%s), with flags=%d, err=%04x endpointidx=%d, image=%d, args=(%d, %d)"),
   164                     aCase.iCase,
   165                     caseName,
   166                     aCase.iFlags,
   167                     aCase.iErrorExpected,
   168                     aCase.iEndpointIndex,
   169                     aCase.iImageIndex,
   170                     aCase.iArg1, aCase.iArg2);
   171     }
   172 
   173 TRemoteTestVerdict CEgltest_Remote_Engine::DoRunRemoteTestCaseL(
   174         TInt aTestCase, const TRemoteTestParams &aParams)
   175     {
   176     TRemoteTestArgs args;
   177     iTestVerdict = ERtvPass;
   178     const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
   179 
   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();
   186 
   187     for(TInt dpyIter = 0; dpyIter < dpyParamsCount; dpyIter++)
   188         {
   189         args.iDisplay = (*displayParams)[dpyIter];
   190         for(TInt epIter = 0; epIter < endpointCount; epIter++)
   191             {
   192             args.iEndpoint = (*endpointParams)[epIter];
   193 
   194             for(TInt imageIter = 0; imageIter < imageCount; imageIter++)
   195                 {
   196                 args.iImage = (*imageParams)[imageIter];
   197 
   198                 RunCaseL(aTestCase, aParams, args);
   199                 if (iLogErrors && iTestVerdict != ERtvPass || iLogging)
   200                     {
   201                     if (iTestVerdict != ERtvPass)
   202                         {
   203                         REMOTE_INFO_PRINTF1(_L("Test failed:"));
   204                         }
   205                     LogDump(si);
   206                     REMOTE_INFO_PRINTF4(_L("Using values: display: %d, endpoint: %d, image: %d"),
   207                             args.iDisplay, args.iEndpoint, args.iImage);
   208                     }
   209                 }
   210             }
   211         }
   212     CleanupStack::PopAndDestroy(3);
   213     return iTestVerdict;
   214     }
   215 
   216 
   217 void CEgltest_Remote_Engine::ActivateVgContextL()
   218     {
   219     if (!iSurface)
   220         {
   221         iSurface = CEglWindowSurface::NewL();
   222         iSurface->CreateL(EStandardSurface, TPoint(0, 110));
   223         }
   224     iSurface->ActivateL();
   225     }
   226 
   227 
   228 TInt CEgltest_Remote_Engine::FillGpuMemory()
   229     {
   230     TSurfaceIndex table[] = 
   231             {
   232             ELargeSurface,
   233             EStandard128sqSurface,
   234             ESmallSurface,
   235             ETinySurface
   236             };
   237     const TInt KNumSurfaceTypes = sizeof(table) / sizeof(table[0]);
   238     
   239     TInt nSurfaces = 0;
   240     const TInt KMaxSurfaceAllocs = 1000;
   241     CSurface **surfaces = new CSurface*[KMaxSurfaceAllocs];
   242     TInt size = 0;
   243     ENGINE_ASSERT(surfaces);
   244     for(TInt i = 0; i < KNumSurfaceTypes; i++)
   245         {
   246         TInt err = KErrNone;
   247         while(err == KErrNone)     
   248             {
   249             ENGINE_ASSERT(nSurfaces < KMaxSurfaceAllocs);
   250             CSurface* s = CSurface::SurfaceFactoryL(ESurfTypePBuffer);
   251             if (s)
   252                 {
   253                 TRAP(err, s->CreateL(table[i]));
   254                 if (err == KErrNone)
   255                     {
   256                     surfaces[nSurfaces++] = s;
   257 //                    s->DrawContentL(TRgb(0x10, 0x20, 0xB0));
   258                     size += s->SizeInBytes();
   259                     }
   260                 }
   261             }
   262         }
   263     RDebug::Printf("nSurfaces=%d", nSurfaces);
   264     while(nSurfaces)
   265         {
   266         delete surfaces[--nSurfaces];
   267         }
   268     delete [] surfaces;
   269     return size;
   270     }
   271 
   272 TInt CEgltest_Remote_Engine::CalculateAvailableGPUMemory()
   273     {
   274     TInt result = 0;
   275     if (ipfnEglQueryProfilingDataNOK)
   276         {
   277         EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   278         ENGINE_ASSERT(display != EGL_NO_DISPLAY);
   279         TInt count;
   280         ipfnEglQueryProfilingDataNOK(
   281                 display, EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK, 
   282                 NULL, 0, &count);
   283         ENGINE_ASSERT(count);
   284         TInt *mem = new TInt[count * 2];
   285         ENGINE_ASSERT(mem);
   286         TInt newCount;
   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 ++)
   292             {
   293             switch(mem[i*2])
   294                 {
   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);
   299                 result = mem[i*2+1];
   300                 break;
   301                 }
   302             }
   303         delete [] mem;
   304         }
   305     else
   306         {
   307 #if 1
   308         result = 1000;
   309 #else
   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();
   314 #endif
   315         }
   316     return result;
   317     }
   318 
   319 
   320 TInt CEgltest_Remote_Engine::CalculateAvailableHeapMemory()
   321     {
   322     TInt biggest = 0;
   323     return User::Heap().Available(biggest);
   324     }
   325 
   326 
   327 void CEgltest_Remote_Engine::CheckForMemoryLeaks()
   328     {
   329     TAvailableMemory mem;
   330     mem.iGpuMemAvailable = CalculateAvailableGPUMemory();
   331     mem.iHeapMemAvailable = CalculateAvailableHeapMemory();
   332     
   333     REMOTE_INFO_PRINTF3(_L("GPU memory available: %d, heapmemory available: %d"), 
   334             mem.iGpuMemAvailable, mem.iHeapMemAvailable);
   335     if (iMemoryStats.Count() ==  KMemStatsReserve)
   336         {
   337         REMOTE_INFO_PRINTF2(_L("false positive HEAP leak possible, as reserved memory is exhausted... (%d)"), KMemStatsReserve);
   338         }
   339     TInt err = iMemoryStats.Append(mem); 
   340     if (err)
   341         {
   342         REMOTE_ERR_PRINTF2(_L("CheckForMemoryLeaks could not append to iMemoryStats. err=%d"), err);
   343         }
   344     }
   345 
   346 void CEgltest_Remote_Engine::CheckForMemoryLeaksFinish()
   347     {
   348     TInt count = iMemoryStats.Count();
   349     if (count)
   350         {
   351         TReal sumGpu = 0.0;
   352         TReal sumHeap = 0.0;
   353         
   354         for(TInt i = 0; i < count; i++)
   355             {
   356             sumGpu += iMemoryStats[i].iGpuMemAvailable;
   357             sumHeap += iMemoryStats[i].iHeapMemAvailable;
   358             }
   359         REMOTE_INFO_PRINTF2(_L("CheckMemoryLeaksFinish - average = %6.2f"), sumGpu / count);
   360         REMOTE_INFO_PRINTF2(_L("CheckMemoryLeaksFinish - average = %6.2f"), sumHeap / count);
   361         }
   362     else
   363         {
   364         REMOTE_INFO_PRINTF1(_L("CheckMemoryLeaksFinish - no data collected"));
   365         }
   366     iMemoryStats.Close();
   367     }
   368 
   369 TRemoteTestVerdict ConvertToLocalVerdict(TInt aVerdict)
   370     {
   371     switch(aVerdict)
   372         {
   373         case EPass:
   374             return ERtvPass;
   375         case EFail:
   376             return ERtvFail;
   377         }
   378         return ERtvInconclusive;
   379     }
   380 
   381 void CEgltest_Remote_Engine::RunCaseL(TInt aTestCase, const TRemoteTestParams &aParams, const TRemoteTestArgs& aArgs)
   382     {
   383     const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
   384     EGLDisplay dpy = aArgs.iDisplay;
   385     EGLImageKHR image = aArgs.iImage;
   386     EGLEndpointNOK endpoint = aArgs.iEndpoint;
   387 
   388     switch (aTestCase)
   389         {
   390         case EInitializeCase:
   391             REMOTE_INFO_PRINTF1(_L("calling EglStartL()"));
   392             EglStartL();
   393             break;
   394 
   395         case ECreateEndpointCase:
   396             CreateEndpointCaseL(aParams, aArgs);
   397             break;
   398 
   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)
   403                 {
   404                 iEglImage[si.iEndpointIndex] = image;
   405                 }
   406             break;
   407 
   408         case ECompareImageCase:
   409             if (iEglImage[si.iEndpointIndex] == EGL_NO_IMAGE_KHR)
   410                 {
   411                 REMOTE_ERR_PRINTF2(_L("Image at index %d is not a valid eglImage"), si.iEndpointIndex);
   412                 iTestVerdict = ERtvFail;
   413                 }
   414             else
   415                 {
   416                 ActivateVgContextL();
   417 
   418                 CTestCFbsImage *image = CTestCFbsImage::NewL(si.iImageIndex);
   419                 CleanupStack::PushL(image);
   420                 CTestVgEglImage *vgImage = CTestVgEglImage::New(iEglImage[si.iEndpointIndex]);
   421                 if (!vgImage)
   422                     {
   423                     REMOTE_INFO_PRINTF2(_L("Could not create vgimage from eglimage: endpointindex=%d"), 
   424                             si.iEndpointIndex);
   425                     }
   426                 else
   427                     {
   428                     CleanupStack::PushL(vgImage);
   429                     TBool res = vgImage->CompareImageL(image, !!(si.iFlags & EExpectError));
   430                     if (res != !(si.iFlags & EExpectError))
   431                         {
   432                         if (iLogErrors)
   433                             {
   434                         REMOTE_ERR_PRINTF1(_L("Pixel comparison failed...."));
   435                             }
   436                         iTestVerdict = ERtvFail;
   437                         }
   438                     else if (!(si.iFlags & EExpectError))
   439                         {
   440                         // Extra check that ANOTHER image doesn't match the image
   441                         // we compared with.
   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);
   448                         if (res)
   449                             {
   450                             REMOTE_ERR_PRINTF1(_L("Pixel comparison didn't fail - two images the same?...."));
   451                             iTestVerdict = ERtvFail;
   452                             }
   453                         CleanupStack::PopAndDestroy(image2);
   454                         }
   455                     CleanupStack::PopAndDestroy(vgImage);
   456                     }
   457                 CleanupStack::PopAndDestroy(image);
   458                 }
   459             break;
   460 
   461         case EReleaseImageCase:
   462             ReleaseImageCaseL(aParams, aArgs);
   463             break;
   464 
   465         case EBeginStreamingCase:
   466             CHECK_BOOL_RET(EndpointBeginStreaming, "eglEndpointBeginStreaming");
   467             break;
   468 
   469         case EEndStreamingCase:
   470             CHECK_BOOL_RET(EndpointEndStreaming, "eglEndpointEndStreaming");
   471             break;
   472 
   473         case EDestroyEndpointCase:
   474             CHECK_BOOL_RET(DestroyEndpoint, "eglDestroyEndpoint");
   475             break;
   476 
   477         case EGetAttribCase:
   478             {
   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)
   484                 {
   485                 CheckReturn(value, si, EGL_FALSE,_S("EGL_FALSE") ,_S("eglGetEndpointAttrib"));
   486                 }
   487             else
   488                 {
   489                 EGLint err = eglGetError();
   490                 if (err != EGL_SUCCESS)
   491                     {
   492                     REMOTE_ERR_PRINTF2(_L("Got an error (%x) on successful call to eglGetEndpointAttrib, when expecting EGL_SUCCESS in error"),
   493                             err);
   494                     iTestVerdict = ERtvFail;
   495                     }
   496                 }
   497             if (value != si.iArg2)
   498                 {
   499                 REMOTE_ERR_PRINTF4(_L("GetEndpointAttrib(%04x), got %d, expected %d"), si.iArg1, value, si.iArg2);
   500                 iTestVerdict = ERtvFail;
   501                 }
   502             }
   503             break;
   504 
   505         case ESetAttribCase:
   506             {
   507             EGLBoolean ret = EglEndpoint().SetEndpointAttrib(dpy, endpoint, si.iArg1, si.iArg2);
   508             CHECK_RETURN(ret, EGL_FALSE, _S("eglSetEndpointAttrib"));
   509             }
   510             break;
   511 
   512         case EDestroyEglImageCase:
   513             {
   514             EGLBoolean ret = EglEndpoint().DestroyImage(dpy, image);
   515             CHECK_RETURN(ret, EGL_FALSE, _S("eglDestroyImageKHR"));
   516             }
   517 			break;
   518 
   519         case ECreateVgImageCase:
   520             {
   521             // For a VgImage to be possible to create, we need to have a EglSurface.
   522             ActivateVgContextL();
   523 
   524             TRAPD(err, iVgImage[si.iImageIndex] = CTestVgEglImage::NewL(iEglImage[si.iEndpointIndex]));
   525             if ((si.iFlags & EExpectFailureMask) && err == KErrNone)
   526                 {
   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;
   531                 }
   532             else if (!(si.iFlags & EExpectFailureMask) && err != KErrNone)
   533                 {
   534                 REMOTE_ERR_PRINTF1(_L("Failed to create VGImage when we expected to succeed"));
   535                 iTestVerdict = ERtvFail;
   536                 }
   537             }
   538             break;
   539 
   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:
   544             {
   545             ActivateVgContextL();
   546             CTestVgEglImage *vgImage = iVgImage[si.iImageIndex];
   547             if (!vgImage)
   548                 {
   549                 // Image not usable!
   550                 REMOTE_ERR_PRINTF1(_L("VGImage is not present"));
   551                 iTestVerdict = ERtvFail;
   552                 }
   553             else
   554                 {
   555                 vgDrawImage(vgImage->VGImage());
   556                 VGint err = vgGetError();
   557                 if (err != VG_NO_ERROR)
   558                     {
   559                     iTestVerdict = ERtvFail;
   560                     }
   561 #if 0
   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);
   569 #endif
   570                 }
   571             // If we get here, the image is "working" - we expect to panic or crash if it's not...
   572             }
   573             break;
   574 
   575         case EDestroyVgImageCase:
   576             delete iVgImage[si.iImageIndex];
   577             iVgImage[si.iImageIndex] = NULL;
   578             break;
   579 
   580         case ERequestNotificationCase:
   581             RequestNotificationL(aParams, aArgs);
   582             break;
   583 
   584         case ECancelNotificationCase:
   585             CHECK_BOOL_RET(EndpointCancelNotification, "eglEndpointCancelNotification");
   586             break;
   587 
   588         case EWaitForNotificationCase:
   589             {
   590             RTimer timer;
   591             TInt err = timer.CreateLocal();
   592             if (err != KErrNone)
   593                 {
   594                 REMOTE_INFO_PRINTF2(_L("Could not create timer. Error=%d"), err);
   595                 iTestVerdict = ERtvFail;
   596                 }
   597             else
   598                 {
   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.
   607                 timer.Cancel();
   608                 timer.Close();
   609                 if (timerStatus == KErrNone && *requestStatus == KRequestPending)
   610                     {
   611                     result = KErrTimedOut;
   612                     }
   613                 else
   614                     {
   615                     result = requestStatus->Int();
   616                     }
   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)
   621                     {
   622                     iTestVerdict = ERtvFail;
   623                     REMOTE_INFO_PRINTF1(_L("Expected failure, but result was a success"));
   624                     }
   625                 else if (!(si.iFlags & EExpectError) && result < KErrNone)
   626                     {
   627                     iTestVerdict = ERtvFail;
   628                     REMOTE_INFO_PRINTF1(_L("Expected success, but result was a failure"));
   629                     }
   630                 if (result != si.iErrorExpected)
   631                     {
   632                     iTestVerdict = ERtvFail;
   633                     REMOTE_INFO_PRINTF3(_L("EWaitForNotificationCase: Expected error %d, got %d"), si.iErrorExpected, result);
   634                     }
   635                 }
   636             }
   637             break;
   638 
   639         case EGetEndpointDirtyAreaCase:
   640             GetEndpointDirtyAreaL(aParams, aArgs);
   641             break;
   642 
   643         case ETerminateCase:
   644             REMOTE_INFO_PRINTF1(_L("calling EglEndL()"));
   645             EglEndL();
   646             break;
   647             
   648         // Memory leak checking functions.
   649         case ECheckForMemoryLeaks:
   650             CheckForMemoryLeaks();
   651             break;
   652             
   653         case ECheckForMemoryLeaksFinish:
   654             CheckForMemoryLeaksFinish();
   655             break;
   656             
   657             
   658         case EStartLoadThreadCase:
   659             StartThreadL(si.iEndpointIndex);
   660             break;
   661             
   662         case EEndLoadThreadCase:
   663             EndThread(si.iEndpointIndex);
   664             break;
   665             
   666         case ESetVerdictCase:
   667             iTestVerdict = ConvertToLocalVerdict(si.iEndpointIndex);
   668             break;
   669             
   670 
   671         /*
   672          * Debug cases
   673          */
   674 
   675         case EBreakPointCase:
   676             __BREAKPOINT();
   677             break;
   678 
   679         case ELogEnableCase:
   680             iLogging = ETrue;
   681             break;
   682             
   683         case EPanicCase:
   684             User::Panic(_L("EPanicCase"), -1);
   685             break;
   686 
   687         default:
   688             REMOTE_ERR_PRINTF2(_L("Invalid testcase %d"), aTestCase);
   689             User::Invariant();
   690             break;
   691         }
   692     }
   693 
   694 
   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)
   698     {
   699     const TInt KStackSize = 12000;
   700     const TInt KHeapMinSize = 16000;
   701     const TInt KHeapMaxSize = 1000000;
   702 
   703     if (aThreadNumber >= KMaxLoadThreads)
   704         {
   705         User::Panic(_L("StartThreadL"), __LINE__);
   706         }
   707     
   708     __e32_atomic_store_rel32(&iStopThreadFlag[aThreadNumber], EFalse);
   709     
   710     TUint32 random = Math::Random();
   711     TName threadName;
   712     _LIT(KThreadNameFormat, "%S-%u");
   713 
   714     // Create a load-thread.
   715     _LIT(KThreadName, "EpTestLoadThread");
   716     threadName.Format(KThreadNameFormat, &KThreadName, random);
   717     TThreadFunction threadFunc = GetThreadFunction(aThreadNumber);
   718     if (threadFunc == NULL)
   719         {
   720         REMOTE_ERR_PRINTF2(_L("Requested thread function %d, got NULL pointer back!"), aThreadNumber);
   721         User::Leave(KErrArgument);
   722         }
   723     TInt err = iLoadThread[aThreadNumber].Create(threadName, threadFunc, 
   724                     KStackSize, KHeapMinSize, KHeapMaxSize, this, EOwnerThread);
   725     if(err != KErrNone)
   726         {
   727         REMOTE_ERR_PRINTF2(_L("Could not create load thread - err=%d"), err);
   728         User::Leave(err);
   729         }
   730     iLoadThread[aThreadNumber].Resume();
   731     }
   732 
   733 
   734 void CEgltest_Remote_Engine::EndThread(TInt aThreadNumber)
   735     {
   736     if (aThreadNumber >= KMaxLoadThreads)
   737         {
   738         User::Panic(_L("StartThreadL"), __LINE__);
   739         }
   740 
   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();
   747     }
   748 
   749 
   750 void CEgltest_Remote_Engine::CreateEndpointCaseL(const TRemoteTestParams &aParams, const TRemoteTestArgs& aArgs)
   751     {
   752     const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
   753     EGLDisplay dpy = aArgs.iDisplay;
   754     EGLEndpointNOK endpoint = aArgs.iEndpoint;
   755     const TSurfaceParamsRemote& cp = aParams.iEndpointEngine.iSurfaceParams;
   756 
   757     CEnumParams* endpointTypeParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadEndpointType),
   758                                                             EGL_ENDPOINT_TYPE_CONSUMER_NOK);
   759     CEnumParams* sourceParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadSourceType),
   760                                                    EGL_TSURFACEID_NOK);
   761     CSurfaceIdParams *surfParams = CSurfaceIdParams::NewLC(!!(si.iFlags & EUseBadSurfaceId),
   762                                                            cp.iSurfaceId);
   763 
   764     TInt endpointTypeCount = endpointTypeParams->Count();
   765     TInt sourceCount = sourceParams->Count();
   766     TInt surfCount = surfParams->Count();
   767 
   768     for(TInt typeIter = 0; typeIter < endpointTypeCount; typeIter++)
   769         {
   770         EGLenum type = (*endpointTypeParams)[typeIter];
   771         for(TInt sourceIter = 0; sourceIter < sourceCount; sourceIter++)
   772             {
   773             EGLenum source_type = (*sourceParams)[sourceIter];
   774 
   775             for(TInt surfIter = 0; surfIter < surfCount; surfIter++)
   776                 {
   777                 EGLEndpointSourceNOK source = (EGLEndpointSourceNOK)(&(*surfParams)[surfIter]);
   778                 EGLint *attrib_list = cp.iCommonParams.iUseAttribList?
   779                     const_cast<EGLint *>(cp.iCommonParams.iAttribs):NULL;
   780 
   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)
   784                     {
   785                     iEndpoints[si.iEndpointIndex] = endpoint;
   786                     }
   787                 }
   788             }
   789         }
   790     CleanupStack::PopAndDestroy(3);
   791     }
   792 
   793 
   794 void CEgltest_Remote_Engine::ReleaseImageCaseL(const TRemoteTestParams& aParams, const TRemoteTestArgs& aArgs)
   795     {
   796     const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
   797     EGLDisplay dpy = aArgs.iDisplay;
   798     EGLImageKHR image = aArgs.iImage;
   799     EGLEndpointNOK endpoint = aArgs.iEndpoint;
   800 
   801     static const EGLenum validAPIs[] = { EGL_OPENVG_API, EGL_OPENGL_API, EGL_OPENGL_ES_API };
   802     const TInt validAPIcount = sizeof(validAPIs) / sizeof(validAPIs[0]);
   803 
   804     CEnumParams* enumParams = CEnumParams::NewLC(!!(si.iFlags & EUseBadApi),
   805             validAPIs, validAPIcount, 0);
   806     for(TInt enumIter = 0; enumIter < enumParams->Count(); enumIter++)
   807         {
   808         EGLenum api = (*enumParams)[enumIter];
   809         EGLBoolean ret = EglEndpoint().ReleaseImage(dpy, endpoint, image, api);
   810         CHECK_RETURN(ret, EGL_FALSE, _S("eglReleaseImage"));
   811         }
   812     CleanupStack::PopAndDestroy(enumParams);
   813     }
   814 
   815 void CEgltest_Remote_Engine::RequestNotificationL(const TRemoteTestParams& aParams, const TRemoteTestArgs &aArgs)
   816     {
   817     const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
   818     EGLDisplay dpy = aArgs.iDisplay;
   819     EGLEndpointNOK endpoint = aArgs.iEndpoint;
   820 
   821     CSyncParams* enumParams = CSyncParams::NewLC(!!(si.iFlags & EUseBadSync), &iRequestStatus[si.iEndpointIndex]);
   822     for(TInt enumIter = 0; enumIter < enumParams->Count(); enumIter++)
   823         {
   824         TRequestStatus* sync = (*enumParams)[enumIter];
   825         EGLBoolean ret = EglEndpoint().EndpointRequestNotification(dpy, endpoint, sync);
   826         CHECK_RETURN(ret, EGL_FALSE, _S("eglEndpointRequestNotification"));
   827         }
   828     CleanupStack::PopAndDestroy(enumParams);
   829     }
   830 
   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;
   837 
   838 void CEgltest_Remote_Engine::DoCheckRectsL(EGLint *aRectsBuffer, EGLint aRectCount, EGLint aMaxRects,
   839                                            TInt aRectsIndex, const TRect aSurfaceRect)
   840     {
   841     // Right now, this testing only supports "full surface" rectangles.
   842     ASSERT(aRectsIndex == 0);
   843     EGLint *rects = aRectsBuffer+KBufferArea * 4;
   844 
   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++)
   849         {
   850         if (rects[i] == KMarker)
   851             {
   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);
   854             }
   855         }
   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
   861     // is done here.
   862     for(TInt i = aRectCount * 4; i < aMaxRects * 4; i++)
   863         {
   864         if (rects[i] != KMarker)
   865             {
   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);
   868             }
   869         }
   870     // Check the "bufferaea" before the actual rects - MUST not be touched.
   871     for(TInt i = 0; i < KBufferArea * 4; i++)
   872         {
   873         if (aRectsBuffer[i] != KMarker)
   874             {
   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);
   877             }
   878         }
   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++)
   882         {
   883         if (aRectsBuffer[i] != KMarker)
   884             {
   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);
   887             }
   888         }
   889     if (aRectsIndex == 0)
   890         {
   891         // Check that rectangle matches the full surface extent.
   892         // We should only have ONE rectangle in this case!
   893         if (aRectCount != 1)
   894             {
   895             REMOTE_INFO_PRINTF2(_L("Expected 1 rectangle returned - got %d"), aRectCount);
   896             iTestVerdict = ERtvFail;
   897             }
   898         else
   899             {
   900             TRect returnedRect = TRect(rects[0], rects[1], rects[2], rects[3]);
   901             if (returnedRect != aSurfaceRect)
   902                 {
   903                 REMOTE_INFO_PRINTF1(_L("rectangles do not match!"));
   904                 }
   905             }
   906         }
   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
   910     // returned.
   911     }
   912 
   913 void CEgltest_Remote_Engine::GetEndpointDirtyAreaL(const TRemoteTestParams& aParams, const TRemoteTestArgs& aArgs)
   914     {
   915     const TEngineTestCase &si = aParams.iEndpointEngine.iEngineTestCase;
   916     EGLDisplay dpy = aArgs.iDisplay;
   917     EGLEndpointNOK endpoint = aArgs.iEndpoint;
   918 
   919     EGLint *rects;
   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))
   926         {
   927         rects = NULL;
   928         }
   929     else
   930         {
   931         rectsBuffer = new EGLint[actualRectsSize];
   932         CleanupStack::PushL(rectsBuffer);
   933         rects = rectsBuffer + (KBufferArea * 4);
   934         for(TInt i = 0; i < actualRectsSize; i++)
   935             {
   936             rectsBuffer[i] = KMarker;
   937             }
   938         }
   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))
   942         {
   943         if (rectsBuffer)
   944             {
   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);
   954             }
   955         }
   956     if (rectsBuffer)
   957         {
   958         CleanupStack::PopAndDestroy(rectsBuffer);
   959         }
   960     if (ret != 0 || (si.iFlags & EExpectFailureMask))
   961         {
   962         CHECK_RETURN(ret, EGL_FALSE, _S("eglGetEndpointDirtyArea"));
   963         }
   964     }
   965 
   966 
   967 TInt CEgltest_Remote_Engine::LoadHeapMemory(TAny *aSelf)
   968     {
   969     CEgltest_Remote_Engine* self = reinterpret_cast<CEgltest_Remote_Engine*>(aSelf);
   970     User::SwitchHeap(self->iMainThreadHeap);
   971     CTrapCleanup *cleanUpStack = CTrapCleanup::New();
   972     if (!cleanUpStack)
   973        {
   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__);
   980        return KErrNoMemory;
   981        }
   982 
   983     TRAPD(err, self->LoadHeapMemoryL());
   984     delete cleanUpStack;
   985     if (err != KErrNone)
   986         {
   987         RDebug::Printf("LoadThreadL left with %d", err);
   988         User::Panic(_L("LoadThread"), __LINE__);
   989         }
   990     return err;    
   991     }
   992 
   993 
   994 void CEgltest_Remote_Engine::LoadHeapMemoryL()
   995     {
   996     const TInt KMaxAllocs = 40000;
   997     char **ptr = new char*[KMaxAllocs];
   998     TInt nAllocs = 0;
   999     while(!__e32_atomic_load_acq32(&iStopThreadFlag[EThreadLoadHeapMemory]))
  1000         {
  1001         char *p = new char[1000];
  1002         if (p)
  1003             {
  1004             if (nAllocs >= KMaxAllocs)
  1005                 {
  1006                 User::Panic(_L("KMaxAllocs"), -3);
  1007                 }
  1008             ptr[nAllocs++] = p;
  1009             }
  1010         else
  1011             {
  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++)
  1016                 {
  1017                 // Decrement first, then use as index.
  1018                 delete [] ptr[--nAllocs];
  1019                 }
  1020             User::After(10 * 1000);   // Let others run for a bit
  1021             }
  1022         }
  1023     // Done - let's deallocate.
  1024     while(nAllocs)
  1025         {
  1026         delete [] ptr[--nAllocs];
  1027         }
  1028     delete [] ptr;
  1029     eglReleaseThread();
  1030     }
  1031 
  1032 
  1033 TInt CEgltest_Remote_Engine::LoadGpuMemory(TAny* aSelf)
  1034     { 
  1035     CEgltest_Remote_Engine* self = reinterpret_cast<CEgltest_Remote_Engine*>(aSelf);
  1036     CTrapCleanup *cleanUpStack = CTrapCleanup::New();
  1037     if (!cleanUpStack)
  1038        {
  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;
  1046        }
  1047 
  1048     TRAPD(err, self->LoadGpuMemoryL());
  1049     delete cleanUpStack;
  1050     if (err != KErrNone)
  1051         {
  1052         RDebug::Printf("LoadThreadL left with %d", err);
  1053         User::Panic(_L("LoadThread"), __LINE__);
  1054         }
  1055     return err;
  1056     }
  1057 
  1058 
  1059 void CEgltest_Remote_Engine::LoadGpuMemoryL()
  1060     {
  1061     const TInt KMaxSurfaceAllocs = 1000;
  1062     CSurface **surfaces = new CSurface*[KMaxSurfaceAllocs];
  1063     ENGINE_ASSERT(surfaces);
  1064     TInt nSurfaces = 0;
  1065     while(!__e32_atomic_load_acq32(&iStopThreadFlag[EThreadLoadGpuMemory]))     
  1066         {
  1067         ENGINE_ASSERT(nSurfaces < KMaxSurfaceAllocs);
  1068         CSurface* s = CSurface::SurfaceFactoryL(ESurfTypePBuffer);
  1069         if (s)
  1070             {
  1071             TRAPD(err, s->CreateL(ELargeSurface));
  1072             if (err == KErrNone)
  1073                 {
  1074                 if (nSurfaces >= KMaxSurfaceAllocs)
  1075                     {
  1076                     User::Panic(_L("KMaxAllocs"), -3);
  1077                     }
  1078                 surfaces[nSurfaces++] = s;
  1079                 s->DrawContentL(TRgb(0x10, 0x20, 0xB0));
  1080                 }
  1081             else
  1082                 {
  1083                 delete s;
  1084                 s = NULL;
  1085                 }
  1086             }
  1087         if (!s)
  1088             {
  1089             User::After(100 * 1000);
  1090             TInt nRelease = nSurfaces / 4;
  1091             for(TInt i = 0; i < nRelease; i++)
  1092                 {
  1093                 delete surfaces[--nSurfaces];
  1094                 surfaces[nSurfaces] = NULL;
  1095                 }
  1096             User::After(100 * 1000); // 100 ms. 
  1097             }
  1098         }
  1099     while(nSurfaces)
  1100         {
  1101         delete surfaces[--nSurfaces];
  1102         }
  1103     delete [] surfaces;
  1104     eglReleaseThread();
  1105     }
  1106 
  1107 
  1108 
  1109 TThreadFunction CEgltest_Remote_Engine::GetThreadFunction(TInt aThreadNumber)
  1110     {
  1111     switch(aThreadNumber)
  1112         {
  1113         case EThreadLoadHeapMemory:
  1114             return LoadHeapMemory;
  1115         case EThreadLoadGpuMemory:
  1116             return LoadGpuMemory;
  1117         }
  1118     RDebug::Printf("%s:%d: Unknown thread function %d", __FILE__, __LINE__, aThreadNumber);
  1119     return NULL;
  1120     }