os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_execthread.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "egltest_endpoint_engine_execthread.h"
sl@0
    17
#include <hal.h>
sl@0
    18
sl@0
    19
/* 
sl@0
    20
 * This class forms the execution thread for running EGL commands. 
sl@0
    21
 * This is primarily so that we can perform EglSwapBuffer (EContentUdpateCase)
sl@0
    22
 * BEFORE calling EglReleaseImageNOK on the remote end. Since EglSwapBuffer
sl@0
    23
 * does not complete until the EglReleaseImageNOK is called, we must have a
sl@0
    24
 * separate thread from the thread performing the table reading/controlling.
sl@0
    25
 * 
sl@0
    26
 * Here's a summary of the classes/threads, and what role they play:
sl@0
    27
 * class CEgltest_Local_Engine
sl@0
    28
 *    Controller for the execution of "engine" tables. 
sl@0
    29
 *    
sl@0
    30
 *    This runs in the thread created by the TestExecute Framework itself
sl@0
    31
 *     
sl@0
    32
 *    It coordinates the Local and Remote execution of commands from
sl@0
    33
 *    the table. 
sl@0
    34
 *    
sl@0
    35
 *    When the command sequence switches from local to remote a "command" of 
sl@0
    36
 *    ESyncLocalCase is automatically inserted into the local command stream,
sl@0
    37
 *    and the controller waits for the reply from this Sync before continuing
sl@0
    38
 *    with the remote command. There is one exception: when the 
sl@0
    39
 *    EContentUpdateCase command is issued with ENoSync flag set, a sync is 
sl@0
    40
 *    sent BEFORE the EContentUpdateCase, but no further Sync is performed
sl@0
    41
 *    until the remote thread is complete.
sl@0
    42
 *    
sl@0
    43
 *    The controller also creates a thread to monitor the controller itself
sl@0
    44
 *    and the CEgltest_Local_Engine_Exec thread. See further comemnts in the
sl@0
    45
 *    source of that class.
sl@0
    46
 *    
sl@0
    47
 * class CEgltest_Local_Engine_Exec
sl@0
    48
 *    Runs in a thread created by the CEgltest_Local_Engine thread.
sl@0
    49
 *    
sl@0
    50
 *    Performs the Actual "client" commands for the test-sequence. The reason
sl@0
    51
 *    for a separate execution thread is outlined above. The reason ALL commands
sl@0
    52
 *    must be executed in this thread is that certain EGL commands (e.g. 
sl@0
    53
 *    SwapBuffer) must be executed by a single thread.
sl@0
    54
 *     
sl@0
    55
 * class CEgltest_Remote_Engine
sl@0
    56
 *    Runs in a thread created by the Test Renderstage code. 
sl@0
    57
 *    
sl@0
    58
 *    This thread performs the EglEndpointNOK specific calls. It also does 
sl@0
    59
 *    various image comparisons. All commands sent to this thread will be 
sl@0
    60
 *    synchronous with the controller execution - meaning that a remote 
sl@0
    61
 *    command will be finished by the time the next command in the controller
sl@0
    62
 *    is issued.
sl@0
    63
 */
sl@0
    64
sl@0
    65
const TInt KTerminated = 0xAABBCCDD;
sl@0
    66
sl@0
    67
CEgltest_Local_Engine_Exec::CEgltest_Local_Engine_Exec() 
sl@0
    68
    : iLogging(EFalse), iVerdict(EPass), iSurfaceTypeDisplayed(EFalse)
sl@0
    69
    {
sl@0
    70
    HAL::Get(HALData::EFastCounterFrequency, iFastFreq);
sl@0
    71
    }
sl@0
    72
sl@0
    73
sl@0
    74
CEgltest_Local_Engine_Exec::~CEgltest_Local_Engine_Exec()
sl@0
    75
    {
sl@0
    76
    iParamsInQueue.Close();
sl@0
    77
    iResultOutQueue.Close();
sl@0
    78
    }
sl@0
    79
sl@0
    80
sl@0
    81
CEgltest_Local_Engine_Exec* CEgltest_Local_Engine_Exec::NewL()
sl@0
    82
    {
sl@0
    83
    CEgltest_Local_Engine_Exec *self = new (ELeave) CEgltest_Local_Engine_Exec();
sl@0
    84
    CleanupStack::PushL(self);
sl@0
    85
    self->ConstructL();
sl@0
    86
    CleanupStack::Pop(self);
sl@0
    87
    return self;
sl@0
    88
    }
sl@0
    89
sl@0
    90
void CEgltest_Local_Engine_Exec::ConstructL()
sl@0
    91
    {
sl@0
    92
    TInt err = iResultOutQueue.OpenGlobal(KExecResultQueueName, EOwnerThread);
sl@0
    93
    ENGINE_ASSERT(err == KErrNone);
sl@0
    94
    User::LeaveIfError(err);
sl@0
    95
    err = iParamsInQueue.OpenGlobal(KExecParamsQueueName, EOwnerThread);
sl@0
    96
    ENGINE_ASSERT(err == KErrNone);
sl@0
    97
    User::LeaveIfError(err);
sl@0
    98
    }
sl@0
    99
sl@0
   100
TInt CEgltest_Local_Engine_Exec::ThreadEntry(TAny */* aDummy */)
sl@0
   101
    {
sl@0
   102
    CTrapCleanup *cleanUpStack = CTrapCleanup::New();
sl@0
   103
    if (!cleanUpStack)
sl@0
   104
       {
sl@0
   105
       // Can't use INFO_PRINTF here, as we have not yet
sl@0
   106
       // created the logger object - nor can we until we have
sl@0
   107
       // a working cleanupstack, so we just do our best at a 
sl@0
   108
       // reason able error message.
sl@0
   109
       RDebug::Printf("Could not allocate memory for cleanupStack!");
sl@0
   110
       User::Panic(_L("ExecThread"), __LINE__);
sl@0
   111
       return KErrNoMemory;
sl@0
   112
       }
sl@0
   113
sl@0
   114
    TRAPD(err, ThreadEntryL());
sl@0
   115
    delete cleanUpStack;
sl@0
   116
    if (err != KErrNone)
sl@0
   117
        {
sl@0
   118
        RDebug::Printf("Thread left with err=%d", err);
sl@0
   119
        User::Panic(_L("ExecThread"), __LINE__);
sl@0
   120
        }
sl@0
   121
    return err;
sl@0
   122
    }
sl@0
   123
sl@0
   124
sl@0
   125
void CEgltest_Local_Engine_Exec::ThreadEntryL()
sl@0
   126
    {
sl@0
   127
    CEgltest_Local_Engine_Exec *self = CEgltest_Local_Engine_Exec::NewL(); 
sl@0
   128
    CleanupStack::PushL(self);
sl@0
   129
    TInt err = KErrNone;
sl@0
   130
    TInt ret = 0;
sl@0
   131
    do {
sl@0
   132
        TRAP(err, ret = self->ThreadLoopL());
sl@0
   133
        if (err != KErrNone)
sl@0
   134
            {
sl@0
   135
            self->SetTestStepResult(EFail);
sl@0
   136
            RDebug::Printf("%s:%d: Leaving with %d", __FILE__, __LINE__, err);
sl@0
   137
            User::Leave(err);
sl@0
   138
            }
sl@0
   139
        self->Logger().Close();
sl@0
   140
    } while(ret != KTerminated);
sl@0
   141
    self->TidyUp();
sl@0
   142
    CleanupStack::PopAndDestroy(self);
sl@0
   143
    }
sl@0
   144
sl@0
   145
sl@0
   146
// Initialize EGL, etc. 
sl@0
   147
void CEgltest_Local_Engine_Exec::SetUpL()
sl@0
   148
    {
sl@0
   149
    iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
sl@0
   150
    EGLint err;
sl@0
   151
    if (iDisplay == EGL_NO_DISPLAY)
sl@0
   152
        {
sl@0
   153
        err = eglGetError();
sl@0
   154
        INFO_PRINTF2(_L("eglGetDisplay failed: err = %x"), err);
sl@0
   155
        User::Leave(KErrNotSupported);
sl@0
   156
        }
sl@0
   157
sl@0
   158
    if (!eglInitialize(iDisplay, NULL, NULL))
sl@0
   159
        {
sl@0
   160
        err = eglGetError();
sl@0
   161
        INFO_PRINTF2(_L("EglInitialize failed: err = %x"), err);
sl@0
   162
        User::Leave(KErrNotSupported);
sl@0
   163
        }
sl@0
   164
    }
sl@0
   165
sl@0
   166
void CEgltest_Local_Engine_Exec::TidyUp()
sl@0
   167
    {
sl@0
   168
    // Clean up. 
sl@0
   169
    iSurfaceTypeDisplayed = EFalse;
sl@0
   170
    for(TInt i = 0; i < KMaxEndpoints; i++)
sl@0
   171
        {
sl@0
   172
        if(iSurfaces[i])
sl@0
   173
            {
sl@0
   174
            delete iSurfaces[i];
sl@0
   175
            iSurfaces[i] = NULL;
sl@0
   176
            }
sl@0
   177
        }
sl@0
   178
    eglTerminate(iDisplay);
sl@0
   179
    eglReleaseThread();
sl@0
   180
    }
sl@0
   181
sl@0
   182
void CEgltest_Local_Engine_Exec::SetTestStepResult(TVerdict aVerdict)
sl@0
   183
    {
sl@0
   184
    iVerdict = aVerdict;
sl@0
   185
    }
sl@0
   186
sl@0
   187
TVerdict CEgltest_Local_Engine_Exec::TestStepResult() const
sl@0
   188
    {
sl@0
   189
    return iVerdict;
sl@0
   190
    }
sl@0
   191
    
sl@0
   192
void CEgltest_Local_Engine_Exec::SendResult(const TExecResult &aResult)
sl@0
   193
    {
sl@0
   194
    iResultOutQueue.SendBlocking(aResult);
sl@0
   195
    }
sl@0
   196
sl@0
   197
TInt CEgltest_Local_Engine_Exec::ThreadLoopL()
sl@0
   198
    {
sl@0
   199
    TBool testFinished = EFalse;
sl@0
   200
    TRemoteTestResult result;
sl@0
   201
sl@0
   202
    TEndpointUtil::SetLoggerForProcessWrapperL(iLogger);
sl@0
   203
    do
sl@0
   204
        {
sl@0
   205
        TRemoteTestParamsPacket params;
sl@0
   206
        iParamsInQueue.ReceiveBlocking(params);
sl@0
   207
       
sl@0
   208
        const TEngineTestCase& ec = params.iParams.iEndpointEngine.iEngineTestCase;
sl@0
   209
sl@0
   210
        TInt index = ec.iImageIndex;
sl@0
   211
        TInt endpointIndex = ec.iEndpointIndex;
sl@0
   212
        
sl@0
   213
        if (iLogging)
sl@0
   214
            {
sl@0
   215
            LogDump(Logger(), ec);
sl@0
   216
            }
sl@0
   217
sl@0
   218
        switch(ec.iCase)
sl@0
   219
            {
sl@0
   220
            case EInitializeCase:
sl@0
   221
                TidyUp();
sl@0
   222
                SetUpL();
sl@0
   223
                break;
sl@0
   224
                
sl@0
   225
            case ECreateSurfaceCase:
sl@0
   226
                {
sl@0
   227
                ENGINE_ASSERT(endpointIndex < KMaxEndpoints);
sl@0
   228
                ENGINE_ASSERT(!iSurfaces[endpointIndex]);
sl@0
   229
                TSurfaceType surfType = params.iParams.iEndpointEngine.iSurfaceParams.iSurfaceType;
sl@0
   230
                iSurfaces[endpointIndex] = CSurface::SurfaceFactoryL(surfType);
sl@0
   231
                TRAPD(err, iSurfaces[endpointIndex]->CreateL(index));
sl@0
   232
                if (err == KErrNone)
sl@0
   233
                    {
sl@0
   234
                    if (!iSurfaceTypeDisplayed)
sl@0
   235
                        {
sl@0
   236
                        INFO_PRINTF4(_L("Using surfaces of type %s (%dx%d pixels)"), 
sl@0
   237
                                iSurfaces[endpointIndex]->GetSurfaceTypeStr(),
sl@0
   238
                                        iSurfaces[endpointIndex]->Size().iWidth,
sl@0
   239
                                        iSurfaces[endpointIndex]->Size().iHeight);
sl@0
   240
                        iSurfaceTypeDisplayed = ETrue;
sl@0
   241
                        }
sl@0
   242
                    }
sl@0
   243
                else
sl@0
   244
                    {
sl@0
   245
                    INFO_PRINTF2(_L("Could not create surface, err=%d"), err);
sl@0
   246
                    delete iSurfaces[endpointIndex];
sl@0
   247
                    iSurfaces[endpointIndex] = NULL;
sl@0
   248
                    SetTestStepResult(EFail);
sl@0
   249
                    }
sl@0
   250
                }
sl@0
   251
                break;
sl@0
   252
                
sl@0
   253
            case EDestroySurfaceCase:
sl@0
   254
                {
sl@0
   255
                delete iSurfaces[endpointIndex];
sl@0
   256
                iSurfaces[endpointIndex] = NULL;
sl@0
   257
                }
sl@0
   258
                break;
sl@0
   259
sl@0
   260
            case EContentUpdateCase:
sl@0
   261
                {
sl@0
   262
                TInt err;
sl@0
   263
                if (!iSurfaces[endpointIndex])
sl@0
   264
                    {
sl@0
   265
                    err = KErrNotSupported;
sl@0
   266
                    }
sl@0
   267
                else
sl@0
   268
                    {
sl@0
   269
                    err = iSurfaces[endpointIndex]->SubmitContent(!(ec.iFlags & ENoWait), index);
sl@0
   270
                    }
sl@0
   271
                
sl@0
   272
                if (err != KErrNone)
sl@0
   273
                    {
sl@0
   274
                    ERR_PRINTF2(_L("ContentUpdate failed, err=%d"), err);
sl@0
   275
                    SetTestStepResult(EFail);
sl@0
   276
                    }
sl@0
   277
                }
sl@0
   278
                break;
sl@0
   279
sl@0
   280
            case EDrawContentCase:
sl@0
   281
                if (iSurfaces[endpointIndex])
sl@0
   282
                    {
sl@0
   283
                    TRAPD(err, iSurfaces[endpointIndex]->DrawContentL(index % CTestImage::KImageCount));
sl@0
   284
                    if (err != KErrNone)
sl@0
   285
                        {
sl@0
   286
                        SetTestStepResult(EFail);
sl@0
   287
                        }
sl@0
   288
                    }
sl@0
   289
                else
sl@0
   290
                    {
sl@0
   291
                    SetTestStepResult(EFail);
sl@0
   292
                    }
sl@0
   293
                break;
sl@0
   294
sl@0
   295
            case EBufferCountCase:
sl@0
   296
                {
sl@0
   297
                TBool pass = ETrue;
sl@0
   298
                TSurfaceParamsRemote surfParams;
sl@0
   299
                TInt buffers = 0;
sl@0
   300
                TInt min = ec.iArg1;
sl@0
   301
                TInt max = ec.iArg2;
sl@0
   302
sl@0
   303
                if (!iSurfaces[endpointIndex])
sl@0
   304
                    {
sl@0
   305
                    pass = EFalse;
sl@0
   306
                    }
sl@0
   307
                else
sl@0
   308
                    {
sl@0
   309
                    iSurfaces[endpointIndex]->GetSurfaceParamsL(surfParams);
sl@0
   310
                    buffers = surfParams.iCommonParams.iBuffers;
sl@0
   311
                    if (min && buffers < min)
sl@0
   312
                        {
sl@0
   313
                        pass = EFalse;
sl@0
   314
                        }
sl@0
   315
                    if (max && buffers > max)
sl@0
   316
                        {
sl@0
   317
                        pass = EFalse;
sl@0
   318
                        }
sl@0
   319
                    }
sl@0
   320
                if (!pass)
sl@0
   321
                    {
sl@0
   322
                    INFO_PRINTF4(_L("Surface has %d buffers, test expect [%d..%d] buffers (0 = 'any number') - Test ignored (pass)"),
sl@0
   323
                            buffers, min, max);
sl@0
   324
                    SendResult(TExecResult(EFail, EPass, ec.iCase));
sl@0
   325
                    testFinished = ETrue;
sl@0
   326
                    }
sl@0
   327
                else
sl@0
   328
                    {
sl@0
   329
                    SendResult(TExecResult(EPass, EPass, ec.iCase));
sl@0
   330
                    }
sl@0
   331
                }
sl@0
   332
                break;
sl@0
   333
sl@0
   334
            case ENotifyWhenCase:
sl@0
   335
                {
sl@0
   336
                if (!iSurfaces[endpointIndex])
sl@0
   337
                    {
sl@0
   338
                    SetTestStepResult(EFail);
sl@0
   339
                    }
sl@0
   340
                else
sl@0
   341
                    {
sl@0
   342
                    TInt err = iSurfaces[endpointIndex]->Notify((TNotification)index, iStatus[endpointIndex], ec.iArg1);
sl@0
   343
                    if (err != ec.iErrorExpected)
sl@0
   344
                        {
sl@0
   345
                        ERR_PRINTF4(_L("Wrong error code from 'NotifyWhen' for notifiction %d - error %d, expected %d"),
sl@0
   346
                                    index, err, ec.iErrorExpected);
sl@0
   347
                        SetTestStepResult(EFail);
sl@0
   348
                        }
sl@0
   349
                    }
sl@0
   350
                }
sl@0
   351
                break;
sl@0
   352
sl@0
   353
            case EWaitForCase:
sl@0
   354
                {
sl@0
   355
#if defined (__WINS__)
sl@0
   356
                const TInt KDiffAllowed = 2500000;   // Max 2500ms difference. Not realy testing anything.
sl@0
   357
#else
sl@0
   358
                const TInt KDiffAllowed = 25000;   // Max 25ms difference.
sl@0
   359
#endif
sl@0
   360
                TUint32 beginTimeStamp = iTimeStamp[endpointIndex];
sl@0
   361
                TUint32 endTimeStamp = User::FastCounter();
sl@0
   362
                ENGINE_ASSERT(endpointIndex < KMaxEndpoints);
sl@0
   363
                if (!iSurfaces[endpointIndex])
sl@0
   364
                    {
sl@0
   365
                    SetTestStepResult(EFail);
sl@0
   366
                    }
sl@0
   367
                else
sl@0
   368
                    {
sl@0
   369
                    TInt err = iSurfaces[endpointIndex]->WaitFor((TNotification)index,
sl@0
   370
                            iStatus[endpointIndex], ec.iArg1, endTimeStamp);
sl@0
   371
    
sl@0
   372
                    //Now, figure out the delta in microseconds.
sl@0
   373
                    TUint32 deltaTime = endTimeStamp - beginTimeStamp;
sl@0
   374
                    deltaTime *= 1000;
sl@0
   375
                    deltaTime /= (iFastFreq / 1000);
sl@0
   376
    
sl@0
   377
                    if (err != ec.iErrorExpected)
sl@0
   378
                        {
sl@0
   379
                        ERR_PRINTF4(_L("Wrong error code from 'WaitFor' for notifiction %d - error %d, expected %d"),
sl@0
   380
                                    index, err, ec.iErrorExpected);
sl@0
   381
                        INFO_PRINTF5(_L("Timeout: %d, beginTimeStamp = %u, endTimeStamp = %u, deltaTime = %u"),
sl@0
   382
                                     ec.iArg1, beginTimeStamp, endTimeStamp, deltaTime);
sl@0
   383
                        SetTestStepResult(EFail);
sl@0
   384
                        }
sl@0
   385
                    // If iArg2 is non-zero, and we waited for "displayed" and no error, check the timestamp.
sl@0
   386
                    if (index == ENotifyWhenDisplayed && err == KErrNone && ec.iArg2)
sl@0
   387
                        {
sl@0
   388
                        if (Abs((TInt)deltaTime - ec.iArg2) > KDiffAllowed)
sl@0
   389
                            {
sl@0
   390
                            ERR_PRINTF3(_L("TimeStamp is incorrect - expected %d microseconds, got %d microseconds"),
sl@0
   391
                                    ec.iArg2, deltaTime);
sl@0
   392
                            INFO_PRINTF4(_L("original timestamp: %u, endpoint ts=%u, iFastFreq=%u"),
sl@0
   393
                                    endTimeStamp, iTimeStamp[endpointIndex], iFastFreq);
sl@0
   394
                            SetTestStepResult(EFail);
sl@0
   395
                            }
sl@0
   396
                        }
sl@0
   397
                    }
sl@0
   398
                }
sl@0
   399
                break;
sl@0
   400
sl@0
   401
            case ETimeStampCase:
sl@0
   402
                iTimeStamp[endpointIndex] = User::FastCounter();
sl@0
   403
                break;
sl@0
   404
                
sl@0
   405
            case EFinishedCase:
sl@0
   406
                SendResult(TExecResult(TestStepResult(), ec.iCase));
sl@0
   407
                testFinished = ETrue;
sl@0
   408
                break;
sl@0
   409
                
sl@0
   410
            case EBreakPointCase:
sl@0
   411
                __BREAKPOINT();
sl@0
   412
                break;
sl@0
   413
                
sl@0
   414
            case ELogEnableCase:
sl@0
   415
                iLogging = ETrue;
sl@0
   416
                break;
sl@0
   417
                
sl@0
   418
            case ESyncLocalCase:
sl@0
   419
                {
sl@0
   420
                SendResult(TExecResult(TestStepResult(), ec.iCase));
sl@0
   421
                }
sl@0
   422
                break;
sl@0
   423
                
sl@0
   424
            case EGetSurfaceParamsCase:
sl@0
   425
                {
sl@0
   426
                TExecResult result(TestStepResult(), ec.iCase);
sl@0
   427
                if (iSurfaces[endpointIndex])
sl@0
   428
                    {
sl@0
   429
                    iSurfaces[endpointIndex]->GetSurfaceParamsL(result.iSurfaceParams);
sl@0
   430
                    }
sl@0
   431
                SendResult(result);
sl@0
   432
                }
sl@0
   433
                break;
sl@0
   434
                
sl@0
   435
            case ETerminateCase:
sl@0
   436
                SendResult(TExecResult(TestStepResult(), ec.iCase));
sl@0
   437
                return KTerminated;
sl@0
   438
                
sl@0
   439
            case ESetVerdictCase:
sl@0
   440
                {
sl@0
   441
                SetTestStepResult(static_cast<TVerdict>(endpointIndex));
sl@0
   442
                TExecResult result(TestStepResult(), ec.iCase);
sl@0
   443
                SendResult(result);
sl@0
   444
                }
sl@0
   445
                break;
sl@0
   446
                
sl@0
   447
            case EPanicCase:
sl@0
   448
                // This part is intended to be used to test the implementation.
sl@0
   449
                // In normal tests, this functionality should not be used.
sl@0
   450
                // If anyone decides to use this for some purpose in normal
sl@0
   451
                // code, then please change the above comment to reflect
sl@0
   452
                // that it IS used, and explain why it makes sense.
sl@0
   453
                INFO_PRINTF1(_L("Performing intentional panic!"));
sl@0
   454
                User::Panic(_L("EPanicCase"), -1);
sl@0
   455
                break;
sl@0
   456
                
sl@0
   457
            default:
sl@0
   458
                ERR_PRINTF2(_L("Unknown case: %d"), ec.iCase);
sl@0
   459
                ENGINE_ASSERT(0);
sl@0
   460
                break;
sl@0
   461
            }
sl@0
   462
        }
sl@0
   463
    while(!testFinished);
sl@0
   464
    return KErrNone;
sl@0
   465
    }