os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_execthread.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_execthread.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,465 @@
     1.4 +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "egltest_endpoint_engine_execthread.h"
    1.20 +#include <hal.h>
    1.21 +
    1.22 +/* 
    1.23 + * This class forms the execution thread for running EGL commands. 
    1.24 + * This is primarily so that we can perform EglSwapBuffer (EContentUdpateCase)
    1.25 + * BEFORE calling EglReleaseImageNOK on the remote end. Since EglSwapBuffer
    1.26 + * does not complete until the EglReleaseImageNOK is called, we must have a
    1.27 + * separate thread from the thread performing the table reading/controlling.
    1.28 + * 
    1.29 + * Here's a summary of the classes/threads, and what role they play:
    1.30 + * class CEgltest_Local_Engine
    1.31 + *    Controller for the execution of "engine" tables. 
    1.32 + *    
    1.33 + *    This runs in the thread created by the TestExecute Framework itself
    1.34 + *     
    1.35 + *    It coordinates the Local and Remote execution of commands from
    1.36 + *    the table. 
    1.37 + *    
    1.38 + *    When the command sequence switches from local to remote a "command" of 
    1.39 + *    ESyncLocalCase is automatically inserted into the local command stream,
    1.40 + *    and the controller waits for the reply from this Sync before continuing
    1.41 + *    with the remote command. There is one exception: when the 
    1.42 + *    EContentUpdateCase command is issued with ENoSync flag set, a sync is 
    1.43 + *    sent BEFORE the EContentUpdateCase, but no further Sync is performed
    1.44 + *    until the remote thread is complete.
    1.45 + *    
    1.46 + *    The controller also creates a thread to monitor the controller itself
    1.47 + *    and the CEgltest_Local_Engine_Exec thread. See further comemnts in the
    1.48 + *    source of that class.
    1.49 + *    
    1.50 + * class CEgltest_Local_Engine_Exec
    1.51 + *    Runs in a thread created by the CEgltest_Local_Engine thread.
    1.52 + *    
    1.53 + *    Performs the Actual "client" commands for the test-sequence. The reason
    1.54 + *    for a separate execution thread is outlined above. The reason ALL commands
    1.55 + *    must be executed in this thread is that certain EGL commands (e.g. 
    1.56 + *    SwapBuffer) must be executed by a single thread.
    1.57 + *     
    1.58 + * class CEgltest_Remote_Engine
    1.59 + *    Runs in a thread created by the Test Renderstage code. 
    1.60 + *    
    1.61 + *    This thread performs the EglEndpointNOK specific calls. It also does 
    1.62 + *    various image comparisons. All commands sent to this thread will be 
    1.63 + *    synchronous with the controller execution - meaning that a remote 
    1.64 + *    command will be finished by the time the next command in the controller
    1.65 + *    is issued.
    1.66 + */
    1.67 +
    1.68 +const TInt KTerminated = 0xAABBCCDD;
    1.69 +
    1.70 +CEgltest_Local_Engine_Exec::CEgltest_Local_Engine_Exec() 
    1.71 +    : iLogging(EFalse), iVerdict(EPass), iSurfaceTypeDisplayed(EFalse)
    1.72 +    {
    1.73 +    HAL::Get(HALData::EFastCounterFrequency, iFastFreq);
    1.74 +    }
    1.75 +
    1.76 +
    1.77 +CEgltest_Local_Engine_Exec::~CEgltest_Local_Engine_Exec()
    1.78 +    {
    1.79 +    iParamsInQueue.Close();
    1.80 +    iResultOutQueue.Close();
    1.81 +    }
    1.82 +
    1.83 +
    1.84 +CEgltest_Local_Engine_Exec* CEgltest_Local_Engine_Exec::NewL()
    1.85 +    {
    1.86 +    CEgltest_Local_Engine_Exec *self = new (ELeave) CEgltest_Local_Engine_Exec();
    1.87 +    CleanupStack::PushL(self);
    1.88 +    self->ConstructL();
    1.89 +    CleanupStack::Pop(self);
    1.90 +    return self;
    1.91 +    }
    1.92 +
    1.93 +void CEgltest_Local_Engine_Exec::ConstructL()
    1.94 +    {
    1.95 +    TInt err = iResultOutQueue.OpenGlobal(KExecResultQueueName, EOwnerThread);
    1.96 +    ENGINE_ASSERT(err == KErrNone);
    1.97 +    User::LeaveIfError(err);
    1.98 +    err = iParamsInQueue.OpenGlobal(KExecParamsQueueName, EOwnerThread);
    1.99 +    ENGINE_ASSERT(err == KErrNone);
   1.100 +    User::LeaveIfError(err);
   1.101 +    }
   1.102 +
   1.103 +TInt CEgltest_Local_Engine_Exec::ThreadEntry(TAny */* aDummy */)
   1.104 +    {
   1.105 +    CTrapCleanup *cleanUpStack = CTrapCleanup::New();
   1.106 +    if (!cleanUpStack)
   1.107 +       {
   1.108 +       // Can't use INFO_PRINTF here, as we have not yet
   1.109 +       // created the logger object - nor can we until we have
   1.110 +       // a working cleanupstack, so we just do our best at a 
   1.111 +       // reason able error message.
   1.112 +       RDebug::Printf("Could not allocate memory for cleanupStack!");
   1.113 +       User::Panic(_L("ExecThread"), __LINE__);
   1.114 +       return KErrNoMemory;
   1.115 +       }
   1.116 +
   1.117 +    TRAPD(err, ThreadEntryL());
   1.118 +    delete cleanUpStack;
   1.119 +    if (err != KErrNone)
   1.120 +        {
   1.121 +        RDebug::Printf("Thread left with err=%d", err);
   1.122 +        User::Panic(_L("ExecThread"), __LINE__);
   1.123 +        }
   1.124 +    return err;
   1.125 +    }
   1.126 +
   1.127 +
   1.128 +void CEgltest_Local_Engine_Exec::ThreadEntryL()
   1.129 +    {
   1.130 +    CEgltest_Local_Engine_Exec *self = CEgltest_Local_Engine_Exec::NewL(); 
   1.131 +    CleanupStack::PushL(self);
   1.132 +    TInt err = KErrNone;
   1.133 +    TInt ret = 0;
   1.134 +    do {
   1.135 +        TRAP(err, ret = self->ThreadLoopL());
   1.136 +        if (err != KErrNone)
   1.137 +            {
   1.138 +            self->SetTestStepResult(EFail);
   1.139 +            RDebug::Printf("%s:%d: Leaving with %d", __FILE__, __LINE__, err);
   1.140 +            User::Leave(err);
   1.141 +            }
   1.142 +        self->Logger().Close();
   1.143 +    } while(ret != KTerminated);
   1.144 +    self->TidyUp();
   1.145 +    CleanupStack::PopAndDestroy(self);
   1.146 +    }
   1.147 +
   1.148 +
   1.149 +// Initialize EGL, etc. 
   1.150 +void CEgltest_Local_Engine_Exec::SetUpL()
   1.151 +    {
   1.152 +    iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   1.153 +    EGLint err;
   1.154 +    if (iDisplay == EGL_NO_DISPLAY)
   1.155 +        {
   1.156 +        err = eglGetError();
   1.157 +        INFO_PRINTF2(_L("eglGetDisplay failed: err = %x"), err);
   1.158 +        User::Leave(KErrNotSupported);
   1.159 +        }
   1.160 +
   1.161 +    if (!eglInitialize(iDisplay, NULL, NULL))
   1.162 +        {
   1.163 +        err = eglGetError();
   1.164 +        INFO_PRINTF2(_L("EglInitialize failed: err = %x"), err);
   1.165 +        User::Leave(KErrNotSupported);
   1.166 +        }
   1.167 +    }
   1.168 +
   1.169 +void CEgltest_Local_Engine_Exec::TidyUp()
   1.170 +    {
   1.171 +    // Clean up. 
   1.172 +    iSurfaceTypeDisplayed = EFalse;
   1.173 +    for(TInt i = 0; i < KMaxEndpoints; i++)
   1.174 +        {
   1.175 +        if(iSurfaces[i])
   1.176 +            {
   1.177 +            delete iSurfaces[i];
   1.178 +            iSurfaces[i] = NULL;
   1.179 +            }
   1.180 +        }
   1.181 +    eglTerminate(iDisplay);
   1.182 +    eglReleaseThread();
   1.183 +    }
   1.184 +
   1.185 +void CEgltest_Local_Engine_Exec::SetTestStepResult(TVerdict aVerdict)
   1.186 +    {
   1.187 +    iVerdict = aVerdict;
   1.188 +    }
   1.189 +
   1.190 +TVerdict CEgltest_Local_Engine_Exec::TestStepResult() const
   1.191 +    {
   1.192 +    return iVerdict;
   1.193 +    }
   1.194 +    
   1.195 +void CEgltest_Local_Engine_Exec::SendResult(const TExecResult &aResult)
   1.196 +    {
   1.197 +    iResultOutQueue.SendBlocking(aResult);
   1.198 +    }
   1.199 +
   1.200 +TInt CEgltest_Local_Engine_Exec::ThreadLoopL()
   1.201 +    {
   1.202 +    TBool testFinished = EFalse;
   1.203 +    TRemoteTestResult result;
   1.204 +
   1.205 +    TEndpointUtil::SetLoggerForProcessWrapperL(iLogger);
   1.206 +    do
   1.207 +        {
   1.208 +        TRemoteTestParamsPacket params;
   1.209 +        iParamsInQueue.ReceiveBlocking(params);
   1.210 +       
   1.211 +        const TEngineTestCase& ec = params.iParams.iEndpointEngine.iEngineTestCase;
   1.212 +
   1.213 +        TInt index = ec.iImageIndex;
   1.214 +        TInt endpointIndex = ec.iEndpointIndex;
   1.215 +        
   1.216 +        if (iLogging)
   1.217 +            {
   1.218 +            LogDump(Logger(), ec);
   1.219 +            }
   1.220 +
   1.221 +        switch(ec.iCase)
   1.222 +            {
   1.223 +            case EInitializeCase:
   1.224 +                TidyUp();
   1.225 +                SetUpL();
   1.226 +                break;
   1.227 +                
   1.228 +            case ECreateSurfaceCase:
   1.229 +                {
   1.230 +                ENGINE_ASSERT(endpointIndex < KMaxEndpoints);
   1.231 +                ENGINE_ASSERT(!iSurfaces[endpointIndex]);
   1.232 +                TSurfaceType surfType = params.iParams.iEndpointEngine.iSurfaceParams.iSurfaceType;
   1.233 +                iSurfaces[endpointIndex] = CSurface::SurfaceFactoryL(surfType);
   1.234 +                TRAPD(err, iSurfaces[endpointIndex]->CreateL(index));
   1.235 +                if (err == KErrNone)
   1.236 +                    {
   1.237 +                    if (!iSurfaceTypeDisplayed)
   1.238 +                        {
   1.239 +                        INFO_PRINTF4(_L("Using surfaces of type %s (%dx%d pixels)"), 
   1.240 +                                iSurfaces[endpointIndex]->GetSurfaceTypeStr(),
   1.241 +                                        iSurfaces[endpointIndex]->Size().iWidth,
   1.242 +                                        iSurfaces[endpointIndex]->Size().iHeight);
   1.243 +                        iSurfaceTypeDisplayed = ETrue;
   1.244 +                        }
   1.245 +                    }
   1.246 +                else
   1.247 +                    {
   1.248 +                    INFO_PRINTF2(_L("Could not create surface, err=%d"), err);
   1.249 +                    delete iSurfaces[endpointIndex];
   1.250 +                    iSurfaces[endpointIndex] = NULL;
   1.251 +                    SetTestStepResult(EFail);
   1.252 +                    }
   1.253 +                }
   1.254 +                break;
   1.255 +                
   1.256 +            case EDestroySurfaceCase:
   1.257 +                {
   1.258 +                delete iSurfaces[endpointIndex];
   1.259 +                iSurfaces[endpointIndex] = NULL;
   1.260 +                }
   1.261 +                break;
   1.262 +
   1.263 +            case EContentUpdateCase:
   1.264 +                {
   1.265 +                TInt err;
   1.266 +                if (!iSurfaces[endpointIndex])
   1.267 +                    {
   1.268 +                    err = KErrNotSupported;
   1.269 +                    }
   1.270 +                else
   1.271 +                    {
   1.272 +                    err = iSurfaces[endpointIndex]->SubmitContent(!(ec.iFlags & ENoWait), index);
   1.273 +                    }
   1.274 +                
   1.275 +                if (err != KErrNone)
   1.276 +                    {
   1.277 +                    ERR_PRINTF2(_L("ContentUpdate failed, err=%d"), err);
   1.278 +                    SetTestStepResult(EFail);
   1.279 +                    }
   1.280 +                }
   1.281 +                break;
   1.282 +
   1.283 +            case EDrawContentCase:
   1.284 +                if (iSurfaces[endpointIndex])
   1.285 +                    {
   1.286 +                    TRAPD(err, iSurfaces[endpointIndex]->DrawContentL(index % CTestImage::KImageCount));
   1.287 +                    if (err != KErrNone)
   1.288 +                        {
   1.289 +                        SetTestStepResult(EFail);
   1.290 +                        }
   1.291 +                    }
   1.292 +                else
   1.293 +                    {
   1.294 +                    SetTestStepResult(EFail);
   1.295 +                    }
   1.296 +                break;
   1.297 +
   1.298 +            case EBufferCountCase:
   1.299 +                {
   1.300 +                TBool pass = ETrue;
   1.301 +                TSurfaceParamsRemote surfParams;
   1.302 +                TInt buffers = 0;
   1.303 +                TInt min = ec.iArg1;
   1.304 +                TInt max = ec.iArg2;
   1.305 +
   1.306 +                if (!iSurfaces[endpointIndex])
   1.307 +                    {
   1.308 +                    pass = EFalse;
   1.309 +                    }
   1.310 +                else
   1.311 +                    {
   1.312 +                    iSurfaces[endpointIndex]->GetSurfaceParamsL(surfParams);
   1.313 +                    buffers = surfParams.iCommonParams.iBuffers;
   1.314 +                    if (min && buffers < min)
   1.315 +                        {
   1.316 +                        pass = EFalse;
   1.317 +                        }
   1.318 +                    if (max && buffers > max)
   1.319 +                        {
   1.320 +                        pass = EFalse;
   1.321 +                        }
   1.322 +                    }
   1.323 +                if (!pass)
   1.324 +                    {
   1.325 +                    INFO_PRINTF4(_L("Surface has %d buffers, test expect [%d..%d] buffers (0 = 'any number') - Test ignored (pass)"),
   1.326 +                            buffers, min, max);
   1.327 +                    SendResult(TExecResult(EFail, EPass, ec.iCase));
   1.328 +                    testFinished = ETrue;
   1.329 +                    }
   1.330 +                else
   1.331 +                    {
   1.332 +                    SendResult(TExecResult(EPass, EPass, ec.iCase));
   1.333 +                    }
   1.334 +                }
   1.335 +                break;
   1.336 +
   1.337 +            case ENotifyWhenCase:
   1.338 +                {
   1.339 +                if (!iSurfaces[endpointIndex])
   1.340 +                    {
   1.341 +                    SetTestStepResult(EFail);
   1.342 +                    }
   1.343 +                else
   1.344 +                    {
   1.345 +                    TInt err = iSurfaces[endpointIndex]->Notify((TNotification)index, iStatus[endpointIndex], ec.iArg1);
   1.346 +                    if (err != ec.iErrorExpected)
   1.347 +                        {
   1.348 +                        ERR_PRINTF4(_L("Wrong error code from 'NotifyWhen' for notifiction %d - error %d, expected %d"),
   1.349 +                                    index, err, ec.iErrorExpected);
   1.350 +                        SetTestStepResult(EFail);
   1.351 +                        }
   1.352 +                    }
   1.353 +                }
   1.354 +                break;
   1.355 +
   1.356 +            case EWaitForCase:
   1.357 +                {
   1.358 +#if defined (__WINS__)
   1.359 +                const TInt KDiffAllowed = 2500000;   // Max 2500ms difference. Not realy testing anything.
   1.360 +#else
   1.361 +                const TInt KDiffAllowed = 25000;   // Max 25ms difference.
   1.362 +#endif
   1.363 +                TUint32 beginTimeStamp = iTimeStamp[endpointIndex];
   1.364 +                TUint32 endTimeStamp = User::FastCounter();
   1.365 +                ENGINE_ASSERT(endpointIndex < KMaxEndpoints);
   1.366 +                if (!iSurfaces[endpointIndex])
   1.367 +                    {
   1.368 +                    SetTestStepResult(EFail);
   1.369 +                    }
   1.370 +                else
   1.371 +                    {
   1.372 +                    TInt err = iSurfaces[endpointIndex]->WaitFor((TNotification)index,
   1.373 +                            iStatus[endpointIndex], ec.iArg1, endTimeStamp);
   1.374 +    
   1.375 +                    //Now, figure out the delta in microseconds.
   1.376 +                    TUint32 deltaTime = endTimeStamp - beginTimeStamp;
   1.377 +                    deltaTime *= 1000;
   1.378 +                    deltaTime /= (iFastFreq / 1000);
   1.379 +    
   1.380 +                    if (err != ec.iErrorExpected)
   1.381 +                        {
   1.382 +                        ERR_PRINTF4(_L("Wrong error code from 'WaitFor' for notifiction %d - error %d, expected %d"),
   1.383 +                                    index, err, ec.iErrorExpected);
   1.384 +                        INFO_PRINTF5(_L("Timeout: %d, beginTimeStamp = %u, endTimeStamp = %u, deltaTime = %u"),
   1.385 +                                     ec.iArg1, beginTimeStamp, endTimeStamp, deltaTime);
   1.386 +                        SetTestStepResult(EFail);
   1.387 +                        }
   1.388 +                    // If iArg2 is non-zero, and we waited for "displayed" and no error, check the timestamp.
   1.389 +                    if (index == ENotifyWhenDisplayed && err == KErrNone && ec.iArg2)
   1.390 +                        {
   1.391 +                        if (Abs((TInt)deltaTime - ec.iArg2) > KDiffAllowed)
   1.392 +                            {
   1.393 +                            ERR_PRINTF3(_L("TimeStamp is incorrect - expected %d microseconds, got %d microseconds"),
   1.394 +                                    ec.iArg2, deltaTime);
   1.395 +                            INFO_PRINTF4(_L("original timestamp: %u, endpoint ts=%u, iFastFreq=%u"),
   1.396 +                                    endTimeStamp, iTimeStamp[endpointIndex], iFastFreq);
   1.397 +                            SetTestStepResult(EFail);
   1.398 +                            }
   1.399 +                        }
   1.400 +                    }
   1.401 +                }
   1.402 +                break;
   1.403 +
   1.404 +            case ETimeStampCase:
   1.405 +                iTimeStamp[endpointIndex] = User::FastCounter();
   1.406 +                break;
   1.407 +                
   1.408 +            case EFinishedCase:
   1.409 +                SendResult(TExecResult(TestStepResult(), ec.iCase));
   1.410 +                testFinished = ETrue;
   1.411 +                break;
   1.412 +                
   1.413 +            case EBreakPointCase:
   1.414 +                __BREAKPOINT();
   1.415 +                break;
   1.416 +                
   1.417 +            case ELogEnableCase:
   1.418 +                iLogging = ETrue;
   1.419 +                break;
   1.420 +                
   1.421 +            case ESyncLocalCase:
   1.422 +                {
   1.423 +                SendResult(TExecResult(TestStepResult(), ec.iCase));
   1.424 +                }
   1.425 +                break;
   1.426 +                
   1.427 +            case EGetSurfaceParamsCase:
   1.428 +                {
   1.429 +                TExecResult result(TestStepResult(), ec.iCase);
   1.430 +                if (iSurfaces[endpointIndex])
   1.431 +                    {
   1.432 +                    iSurfaces[endpointIndex]->GetSurfaceParamsL(result.iSurfaceParams);
   1.433 +                    }
   1.434 +                SendResult(result);
   1.435 +                }
   1.436 +                break;
   1.437 +                
   1.438 +            case ETerminateCase:
   1.439 +                SendResult(TExecResult(TestStepResult(), ec.iCase));
   1.440 +                return KTerminated;
   1.441 +                
   1.442 +            case ESetVerdictCase:
   1.443 +                {
   1.444 +                SetTestStepResult(static_cast<TVerdict>(endpointIndex));
   1.445 +                TExecResult result(TestStepResult(), ec.iCase);
   1.446 +                SendResult(result);
   1.447 +                }
   1.448 +                break;
   1.449 +                
   1.450 +            case EPanicCase:
   1.451 +                // This part is intended to be used to test the implementation.
   1.452 +                // In normal tests, this functionality should not be used.
   1.453 +                // If anyone decides to use this for some purpose in normal
   1.454 +                // code, then please change the above comment to reflect
   1.455 +                // that it IS used, and explain why it makes sense.
   1.456 +                INFO_PRINTF1(_L("Performing intentional panic!"));
   1.457 +                User::Panic(_L("EPanicCase"), -1);
   1.458 +                break;
   1.459 +                
   1.460 +            default:
   1.461 +                ERR_PRINTF2(_L("Unknown case: %d"), ec.iCase);
   1.462 +                ENGINE_ASSERT(0);
   1.463 +                break;
   1.464 +            }
   1.465 +        }
   1.466 +    while(!testFinished);
   1.467 +    return KErrNone;
   1.468 +    }