author | Gareth Stockwell <gareth.stockwell@accenture.com> |
Fri, 22 Oct 2010 11:38:29 +0100 | |
branch | bug235_bringup_0 |
changeset 206 | c170e304623f |
parent 0 | 5d03bc08d59c |
permissions | -rw-r--r-- |
// Copyright (c) 2007-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: // #include "tinterleaving.h" #include "tdirectgdieglcontent_client.h" #include "tdirectgdieglcontent_clientserver.h" #include <graphics/sgimage_sw.h> #include <graphics/directgdiimagetarget.h> #include <graphics/directgdidriver.h> #include <e32math.h> /** A utility class used by the templated function CleanupResetAndDestroyPushL() to create a TCleanupItem item that will perform a ResetAndDestroy() operation on the class T type object. Used for cleanup RPointerArray objects. */ template <class T> class CleanupResetAndDestroy { public: static void PushL(T &aRef) { CleanupStack::PushL(TCleanupItem(&ResetAndDestroy, &aRef)); }; private: static void ResetAndDestroy(TAny *aPtr) { (STATIC_CAST(T *, aPtr))->ResetAndDestroy(); }; }; /** Helper function for pushing CleanupResetAndDestroy object onto CleanupStack. */ template <class T> void CleanupResetAndDestroyPushL(T &aRef) { CleanupResetAndDestroy<T>::PushL(aRef); }; CTInterleaving::CTInterleaving() { SetTestStepName(KTDirectGdiInterleavingStep); } CTInterleaving::~CTInterleaving() { } /** @SYMTestCaseID GRAPHICS-DIRECTGDI-INTERLEAVING-0001 @SYMPREQ PREQ39 @SYMREQ REQ9188 REQ9189 REQ9196 REQ9213 REQ9227 REQ9195 REQ9201 REQ9202 REQ9222 REQ9223 REQ9236 REQ9237 @SYMTestCaseDesc Test synchronized drawing with egl content @SYMTestPriority High @SYMTestStatus Implemented @SYMTestActions Establish connection to EglContentServer. Render frame synchronized with EGL content in following way: - Draw multicolor checkboard to gdi target - Get EGL content sgimage id from EglContentServer in synchronous mode. - Using obtained id create DirectGdi image source and draw it on target with DrawResource() method. - Draw semi-transparent vertical bars to gdi target. Repeat above steps a few times. @SYMTestExpectedResults Valid set of bitmaps should be created. These bitmaps should be the same as a reference bitmaps. */ void CTInterleaving::TestSyncL() { _LIT(KTestName, "Interleaving-Sync"); //test case name // start EGL content server REglContentSession eglContentSession; TESTNOERRORL(eglContentSession.Connect()); CleanupClosePushL(eglContentSession); // render few frames synchronized with egl content for(TInt frame=0; frame<10; frame++) { ResetGc(); DrawDirectGdiCheckboardToTarget(); TESTNOERRORL(iGc->GetError()); // get egl content sgimage id TSgDrawableId imageId; TESTNOERRORL(eglContentSession.GetSyncImage(imageId)); DrawImageToTargetL(imageId); TESTNOERRORL(iGc->GetError()); DrawDirectGdiBarsToTarget(); TESTNOERRORL(iGc->GetError()); // save target TBuf<30> testName; testName.Append(KTestName); testName.AppendNum(frame); TESTNOERRORL(CTDirectGdiStepBase::WriteTargetOutput(iTestParams, testName)); } CleanupStack::PopAndDestroy(&eglContentSession); } /** @SYMTestCaseID GRAPHICS-DIRECTGDI-INTERLEAVING-0002 @SYMPREQ PREQ39 @SYMREQ REQ9188 REQ9189 REQ9196 REQ9213 REQ9227 REQ9195 REQ9201 REQ9202 REQ9222 REQ9223 REQ9236 REQ9237 @SYMTestCaseDesc Test asynchronous drawing of egl content @SYMTestPriority High @SYMTestStatus Implemented @SYMTestActions Establish connection to EglContentServer. Render frame in following way: - Draw multicolor checkboard to gdi target - Get EGL content sgimage id and frame number from EglContentServer in asynchronous mode. - Using obtained id create DirectGdi image source and draw it on target with DrawResource() method. - Draw semi-transparent vertical bars to gdi target. - Find currently created target bitmap in stored bitmaps array. Use frame number obtained from EglContentServer as an array index. If it not exists in this array, store it. Otherwise compare it with stored one pixel by pixel. Test fails when this comparison fails. EglContentServer produce ten different frames, so for proper testing repeat above steps at least fifty times. @SYMTestExpectedResults Valid set of bitmaps should be created. These bitmaps should be the same as a reference bitmaps. */ void CTInterleaving::TestAsyncL(TBool aDebug) { _LIT(KTestName, "Interleaving-Async"); //test case name // start EGL content server REglContentSession eglContentSession; TESTNOERRORL(eglContentSession.Connect()); CleanupClosePushL(eglContentSession); // prepare array to store frames RPointerArray<CFbsBitmap> storedBitmaps(KEglContentAsyncMaxFrames); CleanupResetAndDestroyPushL(storedBitmaps); for(TInt i=0; i<KEglContentAsyncMaxFrames; i++) { storedBitmaps.AppendL(NULL); } // prepare line buffers for bitmap comparision TInt bufSize = iGdiTarget->SizeInPixels().iWidth*4; // buffer is 32-bit BGRA HBufC8* lineBuf1 = HBufC8::NewLC(bufSize); HBufC8* lineBuf2 = HBufC8::NewLC(bufSize); // With the EGL context continuously being generated, we cannot guarantee that // all the frames will be retrieved. // However, in theory, the probability of picking each frame can be // approximated to a uniform discrete distribution. // So we can work out how many times we need to pick a frame to get all // the unique frames 99% of the time. // This works out to be approximately 65 times for 10 unique frames. const TInt KNumTriesToGetAllFrames = 65; if(!aDebug) { WARN_PRINTF1(_L("Note: Due to the nature of the test, it may be possible that not all the frames are captured")); } TInt64 seed = (TInt64)User::FastCounter(); // render few frames asynchronous from egl content for(TInt frame=0; frame<KNumTriesToGetAllFrames; frame++) { ResetGc(); DrawDirectGdiCheckboardToTarget(); TESTNOERRORL(iGc->GetError()); // get egl content sgimage id TSgDrawableId imageId; TInt fnum; if(!aDebug) { TESTNOERRORL(eglContentSession.GetAsyncImage(imageId, fnum)); // Due to the nature of the asynchronous test, where the frames are // continuously being rendered and we can only dip in and pick the last // rendered frame, it cannot be guaranteed that all the unique frames will // be retrieved. This could be due to this loop and the EGL content // generation running in harmony. To try to overcome this, introduce // a random delay between 0 and 3 frames (0 seconds to 100 milliseconds - // EGL content generated at 30fps). TInt delay = Math::Rand(seed)%100000; User::After(delay); } else { TESTNOERRORL(eglContentSession.GetAsyncImageDebug(imageId, fnum)); } DrawImageToTargetL(imageId); TESTNOERRORL(iGc->GetError()); DrawDirectGdiBarsToTarget(); TESTNOERRORL(iGc->GetError()); iGdiTarget->Finish(); CFbsBitmap* targetBitmap = iGdiTarget->GetTargetFbsBitmapL(); if(storedBitmaps[fnum] != NULL) { // compare with previously stored bitmap TUint32 cmpMask; // BGRA mask if((iTestParams.iTargetPixelFormat == EUidPixelFormatXRGB_8888) || (iTestParams.iTargetPixelFormat == EUidPixelFormatXRGB_4444)) { cmpMask = 0xffffff00; // exclude unused pixel part from comparision } else { cmpMask = 0xffffffff; } TInt width = targetBitmap->SizeInPixels().iWidth; TInt height = targetBitmap->SizeInPixels().iHeight; TPtr8 linePtr1(lineBuf1->Des()); TPtr8 linePtr2(lineBuf2->Des()); TBool pass = ETrue; // compare pixel by pixel for(TInt line=0; line<height; line++) { targetBitmap->GetScanLine(linePtr1, TPoint(0, line), width, EColor16MA); storedBitmaps[fnum]->GetScanLine(linePtr2, TPoint(0, line), width, EColor16MA); const TUint32* pPtr1 = (const TUint32*)linePtr1.Ptr(); const TUint32* pPtr2 = (const TUint32*)linePtr2.Ptr(); for(TInt x=0; x<width; x++) { if((pPtr1[x] & cmpMask) != (pPtr2[x] & cmpMask)) { pass = EFalse; break; // break inner loop } } if(!pass) break; // break outer loop if test failed in inner loop } if(!pass) { INFO_PRINTF2(_L("Frame %d not equal to previous one"), fnum); TEST(pass); } } else { // copy and store target bitmap storedBitmaps[fnum] = new(ELeave) CFbsBitmap(); TESTL(storedBitmaps[fnum]->Create(targetBitmap->SizeInPixels(), targetBitmap->DisplayMode()) == KErrNone); Mem::Copy((TUint8*)storedBitmaps[fnum]->DataAddress(), (TUint8*)targetBitmap->DataAddress(), storedBitmaps[fnum]->DataStride()*storedBitmaps[fnum]->SizeInPixels().iHeight); // save target TBuf<40> testName; testName.Append(KTestName); if(aDebug) { _LIT(KDebug, "Debug"); testName.Append(KDebug); } testName.AppendNum(fnum); TESTNOERRORL(CTDirectGdiStepBase::WriteTargetOutput(iTestParams, testName)); } } CleanupStack::PopAndDestroy(4, &eglContentSession); } /** Draw multicolor checkboard to gdi target. */ void CTInterleaving::DrawDirectGdiCheckboardToTarget() { const TInt width = iGdiTarget->SizeInPixels().iWidth; const TInt height = iGdiTarget->SizeInPixels().iHeight; const TInt rwidth = 13; const TInt rheight = 13; iGc->SetPenStyle(DirectGdi::ENullPen); iGc->SetBrushStyle(DirectGdi::ESolidBrush); TInt color = 0; for(TInt y=0; y<height; y+=rheight) { for(TInt x=0; x<width; x+=rwidth) { iGc->SetBrushColor(KColor16Table[color%16]); color++; iGc->DrawRect(TRect(TPoint(x, y), TSize(rwidth, rheight))); } } } /** Draw semi-transparent vertical bars to gdi target. */ void CTInterleaving::DrawDirectGdiBarsToTarget() { TPoint pos(40, 40); TSize size(iGdiTarget->SizeInPixels()); size -= TSize(80, 80); TSize barSize(size.iWidth/10, size.iHeight); iGc->SetPenStyle(DirectGdi::ENullPen); iGc->SetBrushStyle(DirectGdi::ESolidBrush); for(TInt i=0; i<size.iWidth; i+=barSize.iWidth) { TRgb color(255, 0, 0, 25*i/barSize.iWidth); iGc->SetBrushColor(color); iGc->DrawRect(TRect(pos+TPoint(i, 0), barSize)); } } /** Draw four rotated EGL images to gdi target. */ void CTInterleaving::DrawImageToTargetL(TSgDrawableId aImageId) { // prepare sgimage from id RSgImage image; TESTNOERRORL(image.Open(aImageId)); CleanupClosePushL(image); TESTNOERRORL(CDirectGdiDriver::Open()); CDirectGdiDriver* dgdiDriver = CDirectGdiDriver::Static(); TESTL(dgdiDriver != NULL); CleanupClosePushL(*dgdiDriver); // prepare DirectGdi image source RDirectGdiDrawableSource source(*dgdiDriver); TESTNOERRORL(source.Create(image)); CleanupClosePushL(source); // draw sgimage resorce on gdi target TDrawableSourceAndEquivRotatedBmps imageSource; imageSource.iDrawableSrc = &source; TPoint pos(20, 20); TSize size(iGdiTarget->SizeInPixels()); size -= TSize(40, 40); size.iWidth /= 2; size.iHeight /= 2; TSize size2(size); size2 -= TSize(10, 10); iGc->DrawResource(TRect(pos, size2), imageSource); TESTNOERRORL(iGc->GetError()); iGc->DrawResource(TRect(pos+TPoint(size.iWidth, 0), size2), imageSource, DirectGdi::EGraphicsRotation90); TESTNOERRORL(iGc->GetError()); iGc->DrawResource(TRect(pos+TPoint(0, size.iHeight), size2), imageSource, DirectGdi::EGraphicsRotation180); TESTNOERRORL(iGc->GetError()); iGc->DrawResource(TRect(pos+size.AsPoint(), size2), imageSource, DirectGdi::EGraphicsRotation270); TESTNOERRORL(iGc->GetError()); CleanupStack::PopAndDestroy(3, &image); } /** Override of base class virtual @leave Gets system wide error code @return - TVerdict code */ TVerdict CTInterleaving::doTestStepPreambleL() { CTDirectGdiStepBase::doTestStepPreambleL(); return TestStepResult(); } /** Override of base class pure virtual Our implementation only gets called if the base class doTestStepPreambleL() did not leave. That being the case, the current test result value will be EPass. @leave Gets system wide error code @return TVerdict code */ TVerdict CTInterleaving::doTestStepL() { // Test for each target pixel format for(TInt targetPixelFormatIndex = iTargetPixelFormatArray.Count() - 1; targetPixelFormatIndex >= 0 ; targetPixelFormatIndex--) { iTestParams.iTargetPixelFormat = iTargetPixelFormatArray[targetPixelFormatIndex]; SetTargetL(iTestParams.iTargetPixelFormat, EOneContextOneTarget, TSize(400, 400)); RunTestsL(); } CloseTMSGraphicsStep(); return TestStepResult(); } /** Override of base class virtual @leave Gets system wide error code @return - TVerdict code */ TVerdict CTInterleaving::doTestStepPostambleL() { CTDirectGdiStepBase::doTestStepPostambleL(); return TestStepResult(); } /** Override of base class pure virtual Lists the tests to be run */ void CTInterleaving::RunTestsL() { if(iUseDirectGdi) { SetTestStepID(_L("GRAPHICS-DIRECTGDI-INTERLEAVING-0001")); TestSyncL(); RecordTestResultL(); SetTestStepID(_L("GRAPHICS-DIRECTGDI-INTERLEAVING-0002")); TestAsyncL(); RecordTestResultL(); SetTestStepID(_L("GRAPHICS-DIRECTGDI-INTERLEAVING-0002")); TestAsyncL(ETrue); RecordTestResultL(); } }