os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpoint_engine_execthread.cpp
First public contribution.
1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "egltest_endpoint_engine_execthread.h"
20 * This class forms the execution thread for running EGL commands.
21 * This is primarily so that we can perform EglSwapBuffer (EContentUdpateCase)
22 * BEFORE calling EglReleaseImageNOK on the remote end. Since EglSwapBuffer
23 * does not complete until the EglReleaseImageNOK is called, we must have a
24 * separate thread from the thread performing the table reading/controlling.
26 * Here's a summary of the classes/threads, and what role they play:
27 * class CEgltest_Local_Engine
28 * Controller for the execution of "engine" tables.
30 * This runs in the thread created by the TestExecute Framework itself
32 * It coordinates the Local and Remote execution of commands from
35 * When the command sequence switches from local to remote a "command" of
36 * ESyncLocalCase is automatically inserted into the local command stream,
37 * and the controller waits for the reply from this Sync before continuing
38 * with the remote command. There is one exception: when the
39 * EContentUpdateCase command is issued with ENoSync flag set, a sync is
40 * sent BEFORE the EContentUpdateCase, but no further Sync is performed
41 * until the remote thread is complete.
43 * The controller also creates a thread to monitor the controller itself
44 * and the CEgltest_Local_Engine_Exec thread. See further comemnts in the
45 * source of that class.
47 * class CEgltest_Local_Engine_Exec
48 * Runs in a thread created by the CEgltest_Local_Engine thread.
50 * Performs the Actual "client" commands for the test-sequence. The reason
51 * for a separate execution thread is outlined above. The reason ALL commands
52 * must be executed in this thread is that certain EGL commands (e.g.
53 * SwapBuffer) must be executed by a single thread.
55 * class CEgltest_Remote_Engine
56 * Runs in a thread created by the Test Renderstage code.
58 * This thread performs the EglEndpointNOK specific calls. It also does
59 * various image comparisons. All commands sent to this thread will be
60 * synchronous with the controller execution - meaning that a remote
61 * command will be finished by the time the next command in the controller
65 const TInt KTerminated = 0xAABBCCDD;
67 CEgltest_Local_Engine_Exec::CEgltest_Local_Engine_Exec()
68 : iLogging(EFalse), iVerdict(EPass), iSurfaceTypeDisplayed(EFalse)
70 HAL::Get(HALData::EFastCounterFrequency, iFastFreq);
74 CEgltest_Local_Engine_Exec::~CEgltest_Local_Engine_Exec()
76 iParamsInQueue.Close();
77 iResultOutQueue.Close();
81 CEgltest_Local_Engine_Exec* CEgltest_Local_Engine_Exec::NewL()
83 CEgltest_Local_Engine_Exec *self = new (ELeave) CEgltest_Local_Engine_Exec();
84 CleanupStack::PushL(self);
86 CleanupStack::Pop(self);
90 void CEgltest_Local_Engine_Exec::ConstructL()
92 TInt err = iResultOutQueue.OpenGlobal(KExecResultQueueName, EOwnerThread);
93 ENGINE_ASSERT(err == KErrNone);
94 User::LeaveIfError(err);
95 err = iParamsInQueue.OpenGlobal(KExecParamsQueueName, EOwnerThread);
96 ENGINE_ASSERT(err == KErrNone);
97 User::LeaveIfError(err);
100 TInt CEgltest_Local_Engine_Exec::ThreadEntry(TAny */* aDummy */)
102 CTrapCleanup *cleanUpStack = CTrapCleanup::New();
105 // Can't use INFO_PRINTF here, as we have not yet
106 // created the logger object - nor can we until we have
107 // a working cleanupstack, so we just do our best at a
108 // reason able error message.
109 RDebug::Printf("Could not allocate memory for cleanupStack!");
110 User::Panic(_L("ExecThread"), __LINE__);
114 TRAPD(err, ThreadEntryL());
118 RDebug::Printf("Thread left with err=%d", err);
119 User::Panic(_L("ExecThread"), __LINE__);
125 void CEgltest_Local_Engine_Exec::ThreadEntryL()
127 CEgltest_Local_Engine_Exec *self = CEgltest_Local_Engine_Exec::NewL();
128 CleanupStack::PushL(self);
132 TRAP(err, ret = self->ThreadLoopL());
135 self->SetTestStepResult(EFail);
136 RDebug::Printf("%s:%d: Leaving with %d", __FILE__, __LINE__, err);
139 self->Logger().Close();
140 } while(ret != KTerminated);
142 CleanupStack::PopAndDestroy(self);
146 // Initialize EGL, etc.
147 void CEgltest_Local_Engine_Exec::SetUpL()
149 iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
151 if (iDisplay == EGL_NO_DISPLAY)
154 INFO_PRINTF2(_L("eglGetDisplay failed: err = %x"), err);
155 User::Leave(KErrNotSupported);
158 if (!eglInitialize(iDisplay, NULL, NULL))
161 INFO_PRINTF2(_L("EglInitialize failed: err = %x"), err);
162 User::Leave(KErrNotSupported);
166 void CEgltest_Local_Engine_Exec::TidyUp()
169 iSurfaceTypeDisplayed = EFalse;
170 for(TInt i = 0; i < KMaxEndpoints; i++)
178 eglTerminate(iDisplay);
182 void CEgltest_Local_Engine_Exec::SetTestStepResult(TVerdict aVerdict)
187 TVerdict CEgltest_Local_Engine_Exec::TestStepResult() const
192 void CEgltest_Local_Engine_Exec::SendResult(const TExecResult &aResult)
194 iResultOutQueue.SendBlocking(aResult);
197 TInt CEgltest_Local_Engine_Exec::ThreadLoopL()
199 TBool testFinished = EFalse;
200 TRemoteTestResult result;
202 TEndpointUtil::SetLoggerForProcessWrapperL(iLogger);
205 TRemoteTestParamsPacket params;
206 iParamsInQueue.ReceiveBlocking(params);
208 const TEngineTestCase& ec = params.iParams.iEndpointEngine.iEngineTestCase;
210 TInt index = ec.iImageIndex;
211 TInt endpointIndex = ec.iEndpointIndex;
215 LogDump(Logger(), ec);
220 case EInitializeCase:
225 case ECreateSurfaceCase:
227 ENGINE_ASSERT(endpointIndex < KMaxEndpoints);
228 ENGINE_ASSERT(!iSurfaces[endpointIndex]);
229 TSurfaceType surfType = params.iParams.iEndpointEngine.iSurfaceParams.iSurfaceType;
230 iSurfaces[endpointIndex] = CSurface::SurfaceFactoryL(surfType);
231 TRAPD(err, iSurfaces[endpointIndex]->CreateL(index));
234 if (!iSurfaceTypeDisplayed)
236 INFO_PRINTF4(_L("Using surfaces of type %s (%dx%d pixels)"),
237 iSurfaces[endpointIndex]->GetSurfaceTypeStr(),
238 iSurfaces[endpointIndex]->Size().iWidth,
239 iSurfaces[endpointIndex]->Size().iHeight);
240 iSurfaceTypeDisplayed = ETrue;
245 INFO_PRINTF2(_L("Could not create surface, err=%d"), err);
246 delete iSurfaces[endpointIndex];
247 iSurfaces[endpointIndex] = NULL;
248 SetTestStepResult(EFail);
253 case EDestroySurfaceCase:
255 delete iSurfaces[endpointIndex];
256 iSurfaces[endpointIndex] = NULL;
260 case EContentUpdateCase:
263 if (!iSurfaces[endpointIndex])
265 err = KErrNotSupported;
269 err = iSurfaces[endpointIndex]->SubmitContent(!(ec.iFlags & ENoWait), index);
274 ERR_PRINTF2(_L("ContentUpdate failed, err=%d"), err);
275 SetTestStepResult(EFail);
280 case EDrawContentCase:
281 if (iSurfaces[endpointIndex])
283 TRAPD(err, iSurfaces[endpointIndex]->DrawContentL(index % CTestImage::KImageCount));
286 SetTestStepResult(EFail);
291 SetTestStepResult(EFail);
295 case EBufferCountCase:
298 TSurfaceParamsRemote surfParams;
303 if (!iSurfaces[endpointIndex])
309 iSurfaces[endpointIndex]->GetSurfaceParamsL(surfParams);
310 buffers = surfParams.iCommonParams.iBuffers;
311 if (min && buffers < min)
315 if (max && buffers > max)
322 INFO_PRINTF4(_L("Surface has %d buffers, test expect [%d..%d] buffers (0 = 'any number') - Test ignored (pass)"),
324 SendResult(TExecResult(EFail, EPass, ec.iCase));
325 testFinished = ETrue;
329 SendResult(TExecResult(EPass, EPass, ec.iCase));
334 case ENotifyWhenCase:
336 if (!iSurfaces[endpointIndex])
338 SetTestStepResult(EFail);
342 TInt err = iSurfaces[endpointIndex]->Notify((TNotification)index, iStatus[endpointIndex], ec.iArg1);
343 if (err != ec.iErrorExpected)
345 ERR_PRINTF4(_L("Wrong error code from 'NotifyWhen' for notifiction %d - error %d, expected %d"),
346 index, err, ec.iErrorExpected);
347 SetTestStepResult(EFail);
355 #if defined (__WINS__)
356 const TInt KDiffAllowed = 2500000; // Max 2500ms difference. Not realy testing anything.
358 const TInt KDiffAllowed = 25000; // Max 25ms difference.
360 TUint32 beginTimeStamp = iTimeStamp[endpointIndex];
361 TUint32 endTimeStamp = User::FastCounter();
362 ENGINE_ASSERT(endpointIndex < KMaxEndpoints);
363 if (!iSurfaces[endpointIndex])
365 SetTestStepResult(EFail);
369 TInt err = iSurfaces[endpointIndex]->WaitFor((TNotification)index,
370 iStatus[endpointIndex], ec.iArg1, endTimeStamp);
372 //Now, figure out the delta in microseconds.
373 TUint32 deltaTime = endTimeStamp - beginTimeStamp;
375 deltaTime /= (iFastFreq / 1000);
377 if (err != ec.iErrorExpected)
379 ERR_PRINTF4(_L("Wrong error code from 'WaitFor' for notifiction %d - error %d, expected %d"),
380 index, err, ec.iErrorExpected);
381 INFO_PRINTF5(_L("Timeout: %d, beginTimeStamp = %u, endTimeStamp = %u, deltaTime = %u"),
382 ec.iArg1, beginTimeStamp, endTimeStamp, deltaTime);
383 SetTestStepResult(EFail);
385 // If iArg2 is non-zero, and we waited for "displayed" and no error, check the timestamp.
386 if (index == ENotifyWhenDisplayed && err == KErrNone && ec.iArg2)
388 if (Abs((TInt)deltaTime - ec.iArg2) > KDiffAllowed)
390 ERR_PRINTF3(_L("TimeStamp is incorrect - expected %d microseconds, got %d microseconds"),
391 ec.iArg2, deltaTime);
392 INFO_PRINTF4(_L("original timestamp: %u, endpoint ts=%u, iFastFreq=%u"),
393 endTimeStamp, iTimeStamp[endpointIndex], iFastFreq);
394 SetTestStepResult(EFail);
402 iTimeStamp[endpointIndex] = User::FastCounter();
406 SendResult(TExecResult(TestStepResult(), ec.iCase));
407 testFinished = ETrue;
410 case EBreakPointCase:
420 SendResult(TExecResult(TestStepResult(), ec.iCase));
424 case EGetSurfaceParamsCase:
426 TExecResult result(TestStepResult(), ec.iCase);
427 if (iSurfaces[endpointIndex])
429 iSurfaces[endpointIndex]->GetSurfaceParamsL(result.iSurfaceParams);
436 SendResult(TExecResult(TestStepResult(), ec.iCase));
439 case ESetVerdictCase:
441 SetTestStepResult(static_cast<TVerdict>(endpointIndex));
442 TExecResult result(TestStepResult(), ec.iCase);
448 // This part is intended to be used to test the implementation.
449 // In normal tests, this functionality should not be used.
450 // If anyone decides to use this for some purpose in normal
451 // code, then please change the above comment to reflect
452 // that it IS used, and explain why it makes sense.
453 INFO_PRINTF1(_L("Performing intentional panic!"));
454 User::Panic(_L("EPanicCase"), -1);
458 ERR_PRINTF2(_L("Unknown case: %d"), ec.iCase);
463 while(!testFinished);