os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpointtearing_local.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpointtearing_local.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,240 @@
1.4 +/*
1.5 +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +/**
1.23 + @file
1.24 + @test
1.25 + @internalComponent - Internal Symbian test code
1.26 +*/
1.27 +
1.28 +
1.29 +#include "egltest_endpointtearing.h"
1.30 +#include "egltest_surface.h"
1.31 +#include <e32atomics.h>
1.32 +
1.33 +
1.34 +/**
1.35 +@SYMTestCaseID GRAPHICS-EGL-573
1.36 +
1.37 +@SYMTestPriority medium
1.38 +
1.39 +@SYMPREQ 2670
1.40 +
1.41 +@SYMTestCaseDesc
1.42 +Image tearing test with raw surface manager surface.
1.43 +Check that there is no buffer tearing and that locks are implemented correctly.
1.44 +
1.45 +@SYMTestActions
1.46 +Create a Raw Surface Manager surface.
1.47 +1) Thread B (test application): Fill the buffers with colours mostly red, and
1.48 + mostly blue, and mostly green if triple buffered. This is done so that
1.49 + there is a value greater than zero in all colour channels.
1.50 +2) Thread A (wserve): Create an endpoint from the surface belonging to the window
1.51 +3) Thread B: Submit update.
1.52 +4) Thread A: Begin streaming block
1.53 +5) Thread A in the windows server for ten seconds, as fast as possible:
1.54 +6) Thread A: Acquire an EGLImage from this endpoint
1.55 +7) Thread A: Check that the resulting image all a solid colour. Five samples,
1.56 + one at the centre and at the four corners should be sufficient.
1.57 +8) Thread A: Release the EGLImage
1.58 +9) In thread B, whilst thread A is running: fill surface with different solid
1.59 + colours, and call Submit Update. Run this thread as fast a possible, with the
1.60 + same priority as thread A. The solid colour used should be varied for each
1.61 + iteration. Do not synchronize threads A and B, but random waits (using delay
1.62 + loops) may be used to give each thread a variation and reduce any
1.63 + synchronization in the EGL code.
1.64 +10) Thread A: End the streaming block
1.65 +11) Thread A & B: Close and delete resources.
1.66 +
1.67 +@SYMTestExpectedResults
1.68 +Each acquired image from the endpoint is a solid colour,
1.69 +calculated by comparing all the corners and the center pixel.
1.70 +*/
1.71 +
1.72 +
1.73 +CEglTest_LocalTestStep_EndpointTearing::CEglTest_LocalTestStep_EndpointTearing() :
1.74 + CLocalTestStepBase(ETestUidEndpointTearing)
1.75 + {
1.76 + }
1.77 +
1.78 +
1.79 +CEglTest_LocalTestStep_EndpointTearing::~CEglTest_LocalTestStep_EndpointTearing()
1.80 + {
1.81 + }
1.82 +
1.83 +void CEglTest_LocalTestStep_EndpointTearing::DoPreambleL()
1.84 + {
1.85 + //Register the test id.
1.86 + _LIT(KTestId, "573");
1.87 + RegisterTestIdsL(KTestId);
1.88 + SetCurrentTestIds(KTestId);
1.89 +
1.90 + //If this fails, the test will fail in a round about way with EGL_NOT_INITIALIZED.
1.91 + eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL);
1.92 +
1.93 + //Create the fast locaks used for comms between the test thread and the draw thread.
1.94 + User::LeaveIfError(iStartDraw.CreateLocal());
1.95 + User::LeaveIfError(iFirstDrawDone.CreateLocal());
1.96 + }
1.97 +
1.98 +
1.99 +void CEglTest_LocalTestStep_EndpointTearing::DoPostambleL()
1.100 + {
1.101 + iStartDraw.Close();
1.102 + iFirstDrawDone.Close();
1.103 + eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY));
1.104 + }
1.105 +
1.106 +
1.107 +TVerdict CEglTest_LocalTestStep_EndpointTearing::doTestStepL()
1.108 + {
1.109 + //Acquire the start drawing lock to force the draw thread to wait until we signal.
1.110 + iStartDraw.Wait();
1.111 +
1.112 + //Start drawing thread. When this returns, iSurfaceId
1.113 + //contains the surface handle for the surface the thread uses
1.114 + //and the draw thread is waiting on iStartDraw.
1.115 + StartDrawThreadL();
1.116 +
1.117 + //Params for the remote test step.
1.118 + TRemoteTestParams params;
1.119 + params.iEndpointTearing.iSurfaceId = iSurfaceId;
1.120 +
1.121 + //Setup the remote test step. (creates an endpoint).
1.122 + StartRemoteTestStep(params);
1.123 +
1.124 + //Tell the draw thread to continously fill the surface
1.125 + //with a block colour and submit the buffer, honoring the
1.126 + //notifyWhenAvailable semantics.
1.127 + iStartDraw.Signal();
1.128 +
1.129 + //Wait for the first buffer to be drawn, so that the remote side
1.130 + //is guaranteed to be able to begin streaming on the endpoint
1.131 + //when we run the remote test case. The remote side continuously
1.132 + //checks that each acquired image is a solid colour for a set time.
1.133 + iFirstDrawDone.Wait();
1.134 + RunRemoteTestCase(0, TRemoteTestParams());
1.135 +
1.136 + //Stop the drawing thread, so that it does not report a 'not
1.137 + //registered' error when we end the remote test step (destroy ep).
1.138 + StopDrawThread();
1.139 + EndRemoteTestStep(TRemoteTestParams());
1.140 +
1.141 + return TestStepResult();
1.142 + }
1.143 +
1.144 +
1.145 +void CEglTest_LocalTestStep_EndpointTearing::StartDrawThreadL()
1.146 + {
1.147 + //Stack and heap sizes.
1.148 + static const TInt KStackSize = 0x2000; // 8KB
1.149 + static const TInt KHeapMinSize = 0x1000; // 4KB
1.150 + static const TInt KHeapMaxSize = 0x1000000; // 16MB
1.151 +
1.152 + //Create draw thread and wait for rendezvous.
1.153 + User::LeaveIfError(iDrawThread.Create(KNullDesC, DrawThreadEntryPoint, KStackSize, KHeapMinSize, KHeapMaxSize, this));
1.154 + CleanupClosePushL(iDrawThread);
1.155 + iDrawThread.Resume();
1.156 + TRequestStatus rendezvous;
1.157 + iDrawThread.Rendezvous(rendezvous);
1.158 + User::WaitForRequest(rendezvous);
1.159 + User::LeaveIfError(rendezvous.Int());
1.160 + CleanupStack::Pop(&iDrawThread);
1.161 + }
1.162 +
1.163 +
1.164 +void CEglTest_LocalTestStep_EndpointTearing::StopDrawThread()
1.165 + {
1.166 + TRequestStatus logon;
1.167 + iDrawThread.Logon(logon);
1.168 + __e32_atomic_store_rel32(&iStopDrawing, ETrue);
1.169 + User::WaitForRequest(logon);
1.170 + iDrawThread.Close();
1.171 + }
1.172 +
1.173 +
1.174 +TInt CEglTest_LocalTestStep_EndpointTearing::DrawThreadEntryPoint(TAny* aSelf)
1.175 + {
1.176 + CEglTest_LocalTestStep_EndpointTearing* self = static_cast<CEglTest_LocalTestStep_EndpointTearing*>(aSelf);
1.177 + CTrapCleanup* cleanup = CTrapCleanup::New();
1.178 +
1.179 + TRAPD(err,
1.180 + //Create active scheduler.
1.181 + CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
1.182 + CleanupStack::PushL(scheduler);
1.183 + CActiveScheduler::Install(scheduler);
1.184 +
1.185 + //Setup the draw loop.
1.186 + self->EnterDrawLoopL();
1.187 +
1.188 + //Clean up.
1.189 + CleanupStack::PopAndDestroy(scheduler);
1.190 + );
1.191 +
1.192 + __ASSERT_ALWAYS(err == KErrNone, User::PanicUnexpectedLeave());
1.193 + delete cleanup;
1.194 +
1.195 + return KErrNone;
1.196 + }
1.197 +
1.198 +
1.199 +void CEglTest_LocalTestStep_EndpointTearing::EnterDrawLoopL()
1.200 + {
1.201 + //Create a standard surface.
1.202 + CSurface* surface = CSurface::SurfaceFactoryL(ESurfTypeRaw);
1.203 + CleanupStack::PushL(surface);
1.204 + surface->CreateL(ELargeSurface);
1.205 +
1.206 + TRequestStatus availableStat[2];
1.207 + TInt currentStat = 0;
1.208 + TInt currentColour = 0x88CC44;
1.209 +
1.210 + //Take the FirstDrawDone fast lock, save the surfaceId then rendezvous.
1.211 + iFirstDrawDone.Wait();
1.212 + iSurfaceId = surface->SurfaceId();
1.213 + RThread().Rendezvous(KErrNone);
1.214 +
1.215 + //Wait for the signal to draw the first buffer.
1.216 + iStartDraw.Wait();
1.217 + surface->DrawContentL(TRgb(currentColour, 255));
1.218 + surface->Notify(ENotifyWhenAvailable, availableStat[currentStat++ & 1], 0);
1.219 + // We must wait until the image is copied; the endpoint isn't ready until the ContentUpdated has been processed by GCE BE.
1.220 + // It isn't enough to simply call SubmitContentL; there's multiple process/thread boundaries to cross before the endpoint is 'ready'
1.221 + User::LeaveIfError(surface->SubmitContent(ETrue));
1.222 + iFirstDrawDone.Signal();
1.223 +
1.224 + //Loop until we are told to stop drawing.
1.225 + while(!__e32_atomic_load_acq32(&iStopDrawing))
1.226 + {
1.227 + //Draw content, ask for notification when the buffer we have drawn to is available and submit.
1.228 + surface->DrawContentL(TRgb(currentColour, 255));
1.229 + surface->Notify(ENotifyWhenAvailable, availableStat[currentStat++ & 1], 0);
1.230 + User::LeaveIfError(surface->SubmitContent(EFalse));
1.231 +
1.232 + //Wait until the other buffer is free, so we don't tear. There are 2 buffers
1.233 + //in the surface: We asked for ELargeSurface, which is double buffered.
1.234 + TUint32 dummyTimeStamp;
1.235 + TInt err = surface->WaitFor(ENotifyWhenAvailable, availableStat[currentStat & 1], 1000, dummyTimeStamp);
1.236 + User::LeaveIfError(err);
1.237 +
1.238 + //Modify the colour that we draw.
1.239 + currentColour += 16;
1.240 + }
1.241 +
1.242 + CleanupStack::PopAndDestroy(surface);
1.243 + }