diff -r 000000000000 -r bde4ae8d615e os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpointtearing_local.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_endpointtearing_local.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,240 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +/** + @file + @test + @internalComponent - Internal Symbian test code +*/ + + +#include "egltest_endpointtearing.h" +#include "egltest_surface.h" +#include + + +/** +@SYMTestCaseID GRAPHICS-EGL-573 + +@SYMTestPriority medium + +@SYMPREQ 2670 + +@SYMTestCaseDesc +Image tearing test with raw surface manager surface. +Check that there is no buffer tearing and that locks are implemented correctly. + +@SYMTestActions +Create a Raw Surface Manager surface. +1) Thread B (test application): Fill the buffers with colours mostly red, and + mostly blue, and mostly green if triple buffered. This is done so that + there is a value greater than zero in all colour channels. +2) Thread A (wserve): Create an endpoint from the surface belonging to the window +3) Thread B: Submit update. +4) Thread A: Begin streaming block +5) Thread A in the windows server for ten seconds, as fast as possible: +6) Thread A: Acquire an EGLImage from this endpoint +7) Thread A: Check that the resulting image all a solid colour. Five samples, + one at the centre and at the four corners should be sufficient. +8) Thread A: Release the EGLImage +9) In thread B, whilst thread A is running: fill surface with different solid + colours, and call Submit Update. Run this thread as fast a possible, with the + same priority as thread A. The solid colour used should be varied for each + iteration. Do not synchronize threads A and B, but random waits (using delay + loops) may be used to give each thread a variation and reduce any + synchronization in the EGL code. +10) Thread A: End the streaming block +11) Thread A & B: Close and delete resources. + +@SYMTestExpectedResults +Each acquired image from the endpoint is a solid colour, +calculated by comparing all the corners and the center pixel. +*/ + + +CEglTest_LocalTestStep_EndpointTearing::CEglTest_LocalTestStep_EndpointTearing() : + CLocalTestStepBase(ETestUidEndpointTearing) + { + } + + +CEglTest_LocalTestStep_EndpointTearing::~CEglTest_LocalTestStep_EndpointTearing() + { + } + +void CEglTest_LocalTestStep_EndpointTearing::DoPreambleL() + { + //Register the test id. + _LIT(KTestId, "573"); + RegisterTestIdsL(KTestId); + SetCurrentTestIds(KTestId); + + //If this fails, the test will fail in a round about way with EGL_NOT_INITIALIZED. + eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL); + + //Create the fast locaks used for comms between the test thread and the draw thread. + User::LeaveIfError(iStartDraw.CreateLocal()); + User::LeaveIfError(iFirstDrawDone.CreateLocal()); + } + + +void CEglTest_LocalTestStep_EndpointTearing::DoPostambleL() + { + iStartDraw.Close(); + iFirstDrawDone.Close(); + eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY)); + } + + +TVerdict CEglTest_LocalTestStep_EndpointTearing::doTestStepL() + { + //Acquire the start drawing lock to force the draw thread to wait until we signal. + iStartDraw.Wait(); + + //Start drawing thread. When this returns, iSurfaceId + //contains the surface handle for the surface the thread uses + //and the draw thread is waiting on iStartDraw. + StartDrawThreadL(); + + //Params for the remote test step. + TRemoteTestParams params; + params.iEndpointTearing.iSurfaceId = iSurfaceId; + + //Setup the remote test step. (creates an endpoint). + StartRemoteTestStep(params); + + //Tell the draw thread to continously fill the surface + //with a block colour and submit the buffer, honoring the + //notifyWhenAvailable semantics. + iStartDraw.Signal(); + + //Wait for the first buffer to be drawn, so that the remote side + //is guaranteed to be able to begin streaming on the endpoint + //when we run the remote test case. The remote side continuously + //checks that each acquired image is a solid colour for a set time. + iFirstDrawDone.Wait(); + RunRemoteTestCase(0, TRemoteTestParams()); + + //Stop the drawing thread, so that it does not report a 'not + //registered' error when we end the remote test step (destroy ep). + StopDrawThread(); + EndRemoteTestStep(TRemoteTestParams()); + + return TestStepResult(); + } + + +void CEglTest_LocalTestStep_EndpointTearing::StartDrawThreadL() + { + //Stack and heap sizes. + static const TInt KStackSize = 0x2000; // 8KB + static const TInt KHeapMinSize = 0x1000; // 4KB + static const TInt KHeapMaxSize = 0x1000000; // 16MB + + //Create draw thread and wait for rendezvous. + User::LeaveIfError(iDrawThread.Create(KNullDesC, DrawThreadEntryPoint, KStackSize, KHeapMinSize, KHeapMaxSize, this)); + CleanupClosePushL(iDrawThread); + iDrawThread.Resume(); + TRequestStatus rendezvous; + iDrawThread.Rendezvous(rendezvous); + User::WaitForRequest(rendezvous); + User::LeaveIfError(rendezvous.Int()); + CleanupStack::Pop(&iDrawThread); + } + + +void CEglTest_LocalTestStep_EndpointTearing::StopDrawThread() + { + TRequestStatus logon; + iDrawThread.Logon(logon); + __e32_atomic_store_rel32(&iStopDrawing, ETrue); + User::WaitForRequest(logon); + iDrawThread.Close(); + } + + +TInt CEglTest_LocalTestStep_EndpointTearing::DrawThreadEntryPoint(TAny* aSelf) + { + CEglTest_LocalTestStep_EndpointTearing* self = static_cast(aSelf); + CTrapCleanup* cleanup = CTrapCleanup::New(); + + TRAPD(err, + //Create active scheduler. + CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); + CleanupStack::PushL(scheduler); + CActiveScheduler::Install(scheduler); + + //Setup the draw loop. + self->EnterDrawLoopL(); + + //Clean up. + CleanupStack::PopAndDestroy(scheduler); + ); + + __ASSERT_ALWAYS(err == KErrNone, User::PanicUnexpectedLeave()); + delete cleanup; + + return KErrNone; + } + + +void CEglTest_LocalTestStep_EndpointTearing::EnterDrawLoopL() + { + //Create a standard surface. + CSurface* surface = CSurface::SurfaceFactoryL(ESurfTypeRaw); + CleanupStack::PushL(surface); + surface->CreateL(ELargeSurface); + + TRequestStatus availableStat[2]; + TInt currentStat = 0; + TInt currentColour = 0x88CC44; + + //Take the FirstDrawDone fast lock, save the surfaceId then rendezvous. + iFirstDrawDone.Wait(); + iSurfaceId = surface->SurfaceId(); + RThread().Rendezvous(KErrNone); + + //Wait for the signal to draw the first buffer. + iStartDraw.Wait(); + surface->DrawContentL(TRgb(currentColour, 255)); + surface->Notify(ENotifyWhenAvailable, availableStat[currentStat++ & 1], 0); + // We must wait until the image is copied; the endpoint isn't ready until the ContentUpdated has been processed by GCE BE. + // It isn't enough to simply call SubmitContentL; there's multiple process/thread boundaries to cross before the endpoint is 'ready' + User::LeaveIfError(surface->SubmitContent(ETrue)); + iFirstDrawDone.Signal(); + + //Loop until we are told to stop drawing. + while(!__e32_atomic_load_acq32(&iStopDrawing)) + { + //Draw content, ask for notification when the buffer we have drawn to is available and submit. + surface->DrawContentL(TRgb(currentColour, 255)); + surface->Notify(ENotifyWhenAvailable, availableStat[currentStat++ & 1], 0); + User::LeaveIfError(surface->SubmitContent(EFalse)); + + //Wait until the other buffer is free, so we don't tear. There are 2 buffers + //in the surface: We asked for ELargeSurface, which is double buffered. + TUint32 dummyTimeStamp; + TInt err = surface->WaitFor(ENotifyWhenAvailable, availableStat[currentStat & 1], 1000, dummyTimeStamp); + User::LeaveIfError(err); + + //Modify the colour that we draw. + currentColour += 16; + } + + CleanupStack::PopAndDestroy(surface); + }