--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdi/test/tinterleaving.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,485 @@
+// 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();
+ }
+ }