os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpointtearing_local.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 /**
    20  @file
    21  @test
    22  @internalComponent - Internal Symbian test code
    23 */
    24 
    25 
    26 #include "egltest_endpointtearing.h"
    27 #include "egltest_surface.h"
    28 #include <e32atomics.h>
    29 
    30 
    31 /**
    32 @SYMTestCaseID GRAPHICS-EGL-573
    33 
    34 @SYMTestPriority medium
    35 
    36 @SYMPREQ 2670
    37 
    38 @SYMTestCaseDesc
    39 Image tearing test with raw surface manager surface.
    40 Check that there is no buffer tearing and that locks are implemented correctly.
    41 
    42 @SYMTestActions
    43 Create a Raw Surface Manager surface.
    44 1)  Thread B (test application): Fill the buffers with colours mostly red, and 
    45     mostly blue, and mostly green if triple buffered.  This is done so that 
    46     there is a value greater than zero in all colour channels.
    47 2)  Thread A (wserve): Create an endpoint from the surface belonging to the window
    48 3)  Thread B: Submit update.
    49 4)  Thread A: Begin streaming block
    50 5)  Thread A in the windows server for ten seconds, as fast as possible:
    51 6)  Thread A: Acquire an EGLImage from this endpoint
    52 7)  Thread A: Check that the resulting image all a solid colour.  Five samples, 
    53     one at the centre and at the four corners should be sufficient.
    54 8)  Thread A: Release the EGLImage
    55 9)  In thread B, whilst thread A is running: fill surface with different solid 
    56     colours, and call Submit Update. Run this thread as fast a possible, with the 
    57     same priority as thread A. The solid colour used should be varied for each 
    58     iteration.  Do not synchronize threads A and B, but random waits (using delay 
    59     loops) may be used to give each thread a variation and reduce any 
    60     synchronization in the EGL code.
    61 10) Thread A: End the streaming block
    62 11) Thread A & B: Close and delete resources.
    63 
    64 @SYMTestExpectedResults
    65 Each acquired image from the endpoint is a solid colour, 
    66 calculated by comparing all the corners and the center pixel.
    67 */
    68 
    69 
    70 CEglTest_LocalTestStep_EndpointTearing::CEglTest_LocalTestStep_EndpointTearing() :
    71     CLocalTestStepBase(ETestUidEndpointTearing)
    72     {
    73     }
    74 
    75 
    76 CEglTest_LocalTestStep_EndpointTearing::~CEglTest_LocalTestStep_EndpointTearing()
    77     {
    78     }
    79 
    80 void CEglTest_LocalTestStep_EndpointTearing::DoPreambleL()
    81     {
    82     //Register the test id.
    83     _LIT(KTestId, "573");
    84     RegisterTestIdsL(KTestId);
    85     SetCurrentTestIds(KTestId);
    86     
    87     //If this fails, the test will fail in a round about way with EGL_NOT_INITIALIZED.
    88     eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL);
    89     
    90     //Create the fast locaks used for comms between the test thread and the draw thread.
    91     User::LeaveIfError(iStartDraw.CreateLocal());
    92     User::LeaveIfError(iFirstDrawDone.CreateLocal());
    93     }
    94 
    95 
    96 void CEglTest_LocalTestStep_EndpointTearing::DoPostambleL()
    97     {
    98     iStartDraw.Close();
    99     iFirstDrawDone.Close();
   100     eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY));
   101     }
   102 
   103 
   104 TVerdict CEglTest_LocalTestStep_EndpointTearing::doTestStepL()
   105     {
   106     //Acquire the start drawing lock to force the draw thread to wait until we signal.
   107     iStartDraw.Wait();
   108     
   109     //Start drawing thread. When this returns, iSurfaceId
   110     //contains the surface handle for the surface the thread uses
   111     //and the draw thread is waiting on iStartDraw.
   112     StartDrawThreadL();
   113     
   114     //Params for the remote test step.
   115     TRemoteTestParams params;
   116     params.iEndpointTearing.iSurfaceId = iSurfaceId;
   117     
   118     //Setup the remote test step. (creates an endpoint).
   119     StartRemoteTestStep(params);
   120     
   121     //Tell the draw thread to continously fill the surface 
   122     //with a block colour and submit the buffer, honoring the
   123     //notifyWhenAvailable semantics. 
   124     iStartDraw.Signal();
   125     
   126     //Wait for the first buffer to be drawn, so that the remote side
   127     //is guaranteed to be able to begin streaming on the endpoint
   128     //when we run the remote test case. The remote side continuously
   129     //checks that each acquired image is a solid colour for a set time.
   130     iFirstDrawDone.Wait();
   131     RunRemoteTestCase(0, TRemoteTestParams());
   132     
   133     //Stop the drawing thread, so that it does not report a 'not 
   134     //registered' error when we end the remote test step (destroy ep).
   135     StopDrawThread();
   136     EndRemoteTestStep(TRemoteTestParams());
   137     
   138     return TestStepResult();
   139     }
   140 
   141 
   142 void CEglTest_LocalTestStep_EndpointTearing::StartDrawThreadL()
   143     {
   144     //Stack and heap sizes.
   145     static const TInt KStackSize =   0x2000;      //  8KB
   146     static const TInt KHeapMinSize = 0x1000;      //  4KB
   147     static const TInt KHeapMaxSize = 0x1000000;   // 16MB
   148 
   149     //Create draw thread and wait for rendezvous.
   150     User::LeaveIfError(iDrawThread.Create(KNullDesC, DrawThreadEntryPoint, KStackSize, KHeapMinSize, KHeapMaxSize, this));
   151     CleanupClosePushL(iDrawThread);
   152     iDrawThread.Resume();
   153     TRequestStatus rendezvous;
   154     iDrawThread.Rendezvous(rendezvous);
   155     User::WaitForRequest(rendezvous);
   156     User::LeaveIfError(rendezvous.Int());
   157     CleanupStack::Pop(&iDrawThread);
   158     }
   159 
   160 
   161 void CEglTest_LocalTestStep_EndpointTearing::StopDrawThread()
   162     {
   163     TRequestStatus logon;
   164     iDrawThread.Logon(logon);
   165     __e32_atomic_store_rel32(&iStopDrawing, ETrue);
   166     User::WaitForRequest(logon);
   167     iDrawThread.Close();
   168     }
   169 
   170 
   171 TInt CEglTest_LocalTestStep_EndpointTearing::DrawThreadEntryPoint(TAny* aSelf)
   172     {
   173     CEglTest_LocalTestStep_EndpointTearing* self = static_cast<CEglTest_LocalTestStep_EndpointTearing*>(aSelf);
   174     CTrapCleanup* cleanup = CTrapCleanup::New();
   175     
   176     TRAPD(err,
   177         //Create active scheduler.
   178         CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
   179         CleanupStack::PushL(scheduler);
   180         CActiveScheduler::Install(scheduler);
   181 
   182         //Setup the draw loop.
   183         self->EnterDrawLoopL();
   184 
   185         //Clean up.
   186         CleanupStack::PopAndDestroy(scheduler);
   187         );
   188     
   189     __ASSERT_ALWAYS(err == KErrNone, User::PanicUnexpectedLeave());
   190     delete cleanup;
   191     
   192     return KErrNone;
   193     }
   194 
   195 
   196 void CEglTest_LocalTestStep_EndpointTearing::EnterDrawLoopL()
   197     {
   198     //Create a standard surface. 
   199     CSurface* surface = CSurface::SurfaceFactoryL(ESurfTypeRaw);
   200     CleanupStack::PushL(surface);
   201     surface->CreateL(ELargeSurface);
   202     
   203     TRequestStatus availableStat[2];
   204     TInt currentStat = 0;
   205     TInt currentColour = 0x88CC44;
   206     
   207     //Take the FirstDrawDone fast lock, save the surfaceId then rendezvous.
   208     iFirstDrawDone.Wait();
   209     iSurfaceId = surface->SurfaceId();
   210     RThread().Rendezvous(KErrNone);
   211     
   212     //Wait for the signal to draw the first buffer.
   213     iStartDraw.Wait();
   214     surface->DrawContentL(TRgb(currentColour, 255));
   215     surface->Notify(ENotifyWhenAvailable, availableStat[currentStat++ & 1], 0);
   216     // We must wait until the image is copied; the endpoint isn't ready until the ContentUpdated has been processed by GCE BE.
   217     // It isn't enough to simply call SubmitContentL; there's multiple process/thread boundaries to cross before the endpoint is 'ready'
   218     User::LeaveIfError(surface->SubmitContent(ETrue));
   219     iFirstDrawDone.Signal();
   220     
   221     //Loop until we are told to stop drawing.
   222     while(!__e32_atomic_load_acq32(&iStopDrawing))
   223         {
   224         //Draw content, ask for notification when the buffer we have drawn to is available and submit.
   225         surface->DrawContentL(TRgb(currentColour, 255));
   226         surface->Notify(ENotifyWhenAvailable, availableStat[currentStat++ & 1], 0);
   227         User::LeaveIfError(surface->SubmitContent(EFalse));
   228         
   229         //Wait until the other buffer is free, so we don't tear. There are 2 buffers 
   230         //in the surface: We asked for ELargeSurface, which is double buffered.
   231         TUint32 dummyTimeStamp;
   232         TInt err = surface->WaitFor(ENotifyWhenAvailable, availableStat[currentStat & 1], 1000, dummyTimeStamp);
   233         User::LeaveIfError(err);
   234         
   235         //Modify the colour that we draw.
   236         currentColour += 16;
   237         }
   238     
   239     CleanupStack::PopAndDestroy(surface);
   240     }