os/graphics/graphicsdeviceinterface/directgdi/test/tinterleaving.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "tinterleaving.h"
    17 #include "tdirectgdieglcontent_client.h"
    18 #include "tdirectgdieglcontent_clientserver.h"
    19 #include <graphics/sgimage_sw.h>
    20 #include <graphics/directgdiimagetarget.h>
    21 #include <graphics/directgdidriver.h>
    22 #include <e32math.h>
    23 
    24 /**
    25 A utility class used by the templated function CleanupResetAndDestroyPushL() to create
    26 a TCleanupItem item that will perform a ResetAndDestroy() operation on the class T type object.
    27 Used for cleanup RPointerArray objects.
    28 */
    29 template <class T> class CleanupResetAndDestroy
    30 	{
    31 public:
    32 	static void PushL(T &aRef)
    33 		{
    34 		CleanupStack::PushL(TCleanupItem(&ResetAndDestroy, &aRef));
    35 		};
    36 
    37 private:
    38 	static void ResetAndDestroy(TAny *aPtr)
    39 		{
    40 		(STATIC_CAST(T *, aPtr))->ResetAndDestroy();
    41 		};
    42 	};
    43 
    44 /**
    45 Helper function for pushing CleanupResetAndDestroy object onto CleanupStack.
    46 */
    47 template <class T> void CleanupResetAndDestroyPushL(T &aRef)
    48 	{
    49 	CleanupResetAndDestroy<T>::PushL(aRef);
    50 	};
    51 
    52 CTInterleaving::CTInterleaving()
    53 	{
    54 	SetTestStepName(KTDirectGdiInterleavingStep);
    55 	}
    56 
    57 CTInterleaving::~CTInterleaving()
    58 	{
    59 	}
    60 
    61 /**
    62 @SYMTestCaseID  	
    63 	GRAPHICS-DIRECTGDI-INTERLEAVING-0001
    64 	
    65 @SYMPREQ 			
    66 	PREQ39
    67 
    68 @SYMREQ
    69 	REQ9188 
    70 	REQ9189 
    71 	REQ9196 
    72 	REQ9213 
    73 	REQ9227 
    74 	REQ9195
    75 	REQ9201 
    76 	REQ9202 
    77 	REQ9222 
    78 	REQ9223 
    79 	REQ9236 
    80 	REQ9237
    81 	
    82 @SYMTestCaseDesc	
    83 	Test synchronized drawing with egl content
    84 	
    85 @SYMTestPriority	
    86 	High
    87 	
    88 @SYMTestStatus 		
    89 	Implemented
    90 	
    91 @SYMTestActions 	Establish connection to EglContentServer.
    92 					Render frame synchronized with EGL content in following way:
    93 					 - Draw multicolor checkboard to gdi target
    94 					 - Get EGL content sgimage id from EglContentServer in synchronous mode.
    95 					 - Using obtained id create DirectGdi image source and draw it on target with  DrawResource() method.
    96 					 - Draw semi-transparent vertical bars to gdi target.
    97 					Repeat above steps a few times. 
    98 
    99 @SYMTestExpectedResults 
   100 	Valid set of bitmaps should be created.
   101     These bitmaps should be the same as a reference bitmaps.
   102 */
   103 void CTInterleaving::TestSyncL()
   104 	{
   105 	_LIT(KTestName, "Interleaving-Sync"); //test case name
   106 	// start EGL content server
   107 	REglContentSession eglContentSession;
   108 	TESTNOERRORL(eglContentSession.Connect());
   109 	CleanupClosePushL(eglContentSession);
   110 
   111 	// render few frames synchronized with egl content
   112 	for(TInt frame=0; frame<10; frame++)
   113 		{
   114 		ResetGc();
   115 
   116 		DrawDirectGdiCheckboardToTarget();
   117 		TESTNOERRORL(iGc->GetError());
   118 
   119 		// get egl content sgimage id
   120 		TSgDrawableId imageId;
   121 		TESTNOERRORL(eglContentSession.GetSyncImage(imageId));
   122 
   123 		DrawImageToTargetL(imageId);
   124 		TESTNOERRORL(iGc->GetError());
   125 
   126 		DrawDirectGdiBarsToTarget();
   127 		TESTNOERRORL(iGc->GetError());
   128 
   129 		// save target
   130 		TBuf<30> testName;
   131 		testName.Append(KTestName);
   132 		testName.AppendNum(frame);
   133 		TESTNOERRORL(CTDirectGdiStepBase::WriteTargetOutput(iTestParams, testName));
   134 		}
   135 
   136 	CleanupStack::PopAndDestroy(&eglContentSession);
   137 	}
   138 
   139 /**
   140 @SYMTestCaseID  	
   141 	GRAPHICS-DIRECTGDI-INTERLEAVING-0002
   142 	
   143 @SYMPREQ 			
   144 	PREQ39
   145 
   146 @SYMREQ
   147 	REQ9188 
   148 	REQ9189 
   149 	REQ9196 
   150 	REQ9213 
   151 	REQ9227 
   152 	REQ9195
   153 	REQ9201 
   154 	REQ9202 
   155 	REQ9222 
   156 	REQ9223 
   157 	REQ9236 
   158 	REQ9237
   159 	
   160 @SYMTestCaseDesc	
   161 	Test asynchronous drawing of egl content
   162 	
   163 @SYMTestPriority	
   164 	High
   165 	
   166 @SYMTestStatus 		
   167 	Implemented
   168 	
   169 @SYMTestActions 	Establish connection to EglContentServer.
   170 					Render frame in following way:
   171 					 - Draw multicolor checkboard to gdi target
   172 					 - Get EGL content sgimage id and frame number from EglContentServer in asynchronous mode. 
   173 					 - Using obtained id create DirectGdi image source and draw it on target with  DrawResource() method.
   174 					 - Draw semi-transparent vertical bars to gdi target.
   175 					 - Find currently created target bitmap in stored bitmaps array. 
   176 					   Use frame number obtained from EglContentServer as an array index. 
   177 					   If it not exists in this array, store it. Otherwise  compare it with stored one pixel by pixel. 
   178 					   Test fails when this comparison fails.
   179 					EglContentServer produce ten different frames, 
   180 					so for proper testing repeat above steps at least fifty times.
   181 
   182 @SYMTestExpectedResults Valid set of bitmaps should be created.
   183                         These bitmaps should be the same as a reference bitmaps.
   184 */
   185 void CTInterleaving::TestAsyncL(TBool aDebug)
   186 	{
   187 	_LIT(KTestName, "Interleaving-Async"); //test case name
   188 
   189 	// start EGL content server
   190 	REglContentSession eglContentSession;
   191 	TESTNOERRORL(eglContentSession.Connect());
   192 	CleanupClosePushL(eglContentSession);
   193 
   194 	// prepare array to store frames
   195 	RPointerArray<CFbsBitmap> storedBitmaps(KEglContentAsyncMaxFrames);
   196 	CleanupResetAndDestroyPushL(storedBitmaps);
   197 	for(TInt i=0; i<KEglContentAsyncMaxFrames; i++)
   198 		{
   199 		storedBitmaps.AppendL(NULL);
   200 		}
   201 
   202 	// prepare line buffers for bitmap comparision
   203 	TInt bufSize = iGdiTarget->SizeInPixels().iWidth*4; // buffer is 32-bit BGRA
   204 	HBufC8* lineBuf1 = HBufC8::NewLC(bufSize);
   205 	HBufC8* lineBuf2 = HBufC8::NewLC(bufSize);
   206 
   207 	// With the EGL context continuously being generated, we cannot guarantee that
   208 	// all the frames will be retrieved.
   209 	// However, in theory, the probability of picking each frame can be
   210 	// approximated to a uniform discrete distribution.
   211 	// So we can work out how many times we need to pick a frame to get all
   212 	// the unique frames 99% of the time.
   213 	// This works out to be approximately 65 times for 10 unique frames.
   214 	const TInt KNumTriesToGetAllFrames = 65;
   215 
   216 	if(!aDebug)
   217 		{
   218 		WARN_PRINTF1(_L("Note: Due to the nature of the test, it may be possible that not all the frames are captured"));
   219 		}
   220 	TInt64 seed = (TInt64)User::FastCounter();
   221 
   222 	// render few frames asynchronous from egl content
   223 	for(TInt frame=0; frame<KNumTriesToGetAllFrames; frame++)
   224 		{
   225 		ResetGc();
   226 
   227 		DrawDirectGdiCheckboardToTarget();
   228 		TESTNOERRORL(iGc->GetError());
   229 
   230 		// get egl content sgimage id
   231 		TSgDrawableId imageId;
   232 		TInt fnum;
   233 		if(!aDebug)
   234 			{
   235 			TESTNOERRORL(eglContentSession.GetAsyncImage(imageId, fnum));
   236 			// Due to the nature of the asynchronous test, where the frames are
   237 			// continuously being rendered and we can only dip in and pick the last
   238 			// rendered frame, it cannot be guaranteed that all the unique frames will
   239 			// be retrieved.  This could be due to this loop and the EGL content
   240 			// generation running in harmony.  To try to overcome this, introduce
   241 			// a random delay between 0 and 3 frames (0 seconds to 100 milliseconds - 
   242 			// EGL content generated at 30fps).
   243 			TInt delay = Math::Rand(seed)%100000;
   244 			User::After(delay);
   245 			}
   246 		else
   247 			{
   248 			TESTNOERRORL(eglContentSession.GetAsyncImageDebug(imageId, fnum));
   249 			}
   250 
   251 		DrawImageToTargetL(imageId);
   252 		TESTNOERRORL(iGc->GetError());
   253 
   254 		DrawDirectGdiBarsToTarget();
   255 		TESTNOERRORL(iGc->GetError());
   256 
   257 		iGdiTarget->Finish();
   258 		CFbsBitmap* targetBitmap = iGdiTarget->GetTargetFbsBitmapL();
   259 
   260 		if(storedBitmaps[fnum] != NULL)
   261 			{
   262 			// compare with previously stored bitmap
   263 			TUint32 cmpMask; // BGRA mask
   264 			if((iTestParams.iTargetPixelFormat == EUidPixelFormatXRGB_8888) ||
   265 				(iTestParams.iTargetPixelFormat == EUidPixelFormatXRGB_4444))
   266 				{
   267 				cmpMask = 0xffffff00; // exclude unused pixel part from comparision
   268 				}
   269 			else
   270 				{
   271 				cmpMask = 0xffffffff;
   272 				}
   273 
   274 			TInt width = targetBitmap->SizeInPixels().iWidth;
   275 			TInt height = targetBitmap->SizeInPixels().iHeight;
   276 
   277 			TPtr8 linePtr1(lineBuf1->Des());
   278 			TPtr8 linePtr2(lineBuf2->Des());
   279 
   280 			TBool pass = ETrue;
   281 
   282 			// compare pixel by pixel
   283 			for(TInt line=0; line<height; line++)
   284 				{
   285 				targetBitmap->GetScanLine(linePtr1, TPoint(0, line), width, EColor16MA);
   286 				storedBitmaps[fnum]->GetScanLine(linePtr2, TPoint(0, line), width, EColor16MA);
   287 
   288 				const TUint32* pPtr1 = (const TUint32*)linePtr1.Ptr();
   289 				const TUint32* pPtr2 = (const TUint32*)linePtr2.Ptr();
   290 				for(TInt x=0; x<width; x++)
   291 					{
   292 					if((pPtr1[x] & cmpMask) != (pPtr2[x] & cmpMask))
   293 						{
   294 						pass = EFalse;
   295 						break; // break inner loop
   296 						}
   297 					}
   298 
   299 				if(!pass)
   300 					break; // break outer loop if test failed in inner loop
   301 				}
   302 
   303 			if(!pass)
   304 				{
   305 				INFO_PRINTF2(_L("Frame %d not equal to previous one"), fnum);
   306 				TEST(pass);
   307 				}
   308 			}
   309 		else
   310 			{
   311 			// copy and store target bitmap
   312 			storedBitmaps[fnum] = new(ELeave) CFbsBitmap();
   313 			TESTL(storedBitmaps[fnum]->Create(targetBitmap->SizeInPixels(), targetBitmap->DisplayMode()) == KErrNone);
   314 		    Mem::Copy((TUint8*)storedBitmaps[fnum]->DataAddress(),
   315 		    		(TUint8*)targetBitmap->DataAddress(),
   316 		    		storedBitmaps[fnum]->DataStride()*storedBitmaps[fnum]->SizeInPixels().iHeight);
   317 
   318 			// save target
   319 			TBuf<40> testName;
   320 			testName.Append(KTestName);
   321 			if(aDebug)
   322 				{
   323 				_LIT(KDebug, "Debug");
   324 				testName.Append(KDebug);
   325 				}
   326 			testName.AppendNum(fnum);
   327 			TESTNOERRORL(CTDirectGdiStepBase::WriteTargetOutput(iTestParams, testName));
   328 			}
   329 		}
   330 
   331 	CleanupStack::PopAndDestroy(4, &eglContentSession);
   332 	}
   333 
   334 /**
   335 Draw multicolor checkboard to gdi target.
   336 */
   337 void CTInterleaving::DrawDirectGdiCheckboardToTarget()
   338 	{
   339 	const TInt width = iGdiTarget->SizeInPixels().iWidth;
   340 	const TInt height = iGdiTarget->SizeInPixels().iHeight;
   341 	const TInt rwidth = 13;
   342 	const TInt rheight = 13;
   343 
   344 	iGc->SetPenStyle(DirectGdi::ENullPen);
   345 	iGc->SetBrushStyle(DirectGdi::ESolidBrush);
   346 
   347 	TInt color = 0;
   348 	for(TInt y=0; y<height; y+=rheight)
   349 		{
   350 		for(TInt x=0; x<width; x+=rwidth)
   351 			{
   352 			iGc->SetBrushColor(KColor16Table[color%16]);
   353 			color++;
   354 			iGc->DrawRect(TRect(TPoint(x, y), TSize(rwidth, rheight)));
   355 			}
   356 		}
   357 	}
   358 
   359 /**
   360 Draw semi-transparent vertical bars to gdi target.
   361 */
   362 void CTInterleaving::DrawDirectGdiBarsToTarget()
   363 	{
   364 	TPoint pos(40, 40);
   365 	TSize size(iGdiTarget->SizeInPixels());
   366 	size -= TSize(80, 80);
   367 	TSize barSize(size.iWidth/10, size.iHeight);
   368 
   369 	iGc->SetPenStyle(DirectGdi::ENullPen);
   370 	iGc->SetBrushStyle(DirectGdi::ESolidBrush);
   371 
   372 	for(TInt i=0; i<size.iWidth; i+=barSize.iWidth)
   373 		{
   374 		TRgb color(255, 0, 0, 25*i/barSize.iWidth);
   375 		iGc->SetBrushColor(color);
   376 		iGc->DrawRect(TRect(pos+TPoint(i, 0), barSize));
   377 		}
   378 	}
   379 
   380 /**
   381 Draw four rotated EGL images to gdi target.
   382 */
   383 void CTInterleaving::DrawImageToTargetL(TSgDrawableId aImageId)
   384 	{
   385 	// prepare sgimage from id
   386 	RSgImage image;	
   387 	TESTNOERRORL(image.Open(aImageId));
   388 	CleanupClosePushL(image);
   389 
   390 	TESTNOERRORL(CDirectGdiDriver::Open());
   391 
   392 	CDirectGdiDriver* dgdiDriver = CDirectGdiDriver::Static();
   393 	TESTL(dgdiDriver != NULL);	
   394 	CleanupClosePushL(*dgdiDriver);	
   395 
   396 	// prepare DirectGdi image source
   397 	RDirectGdiDrawableSource source(*dgdiDriver);
   398 	TESTNOERRORL(source.Create(image));
   399 	CleanupClosePushL(source);
   400 
   401 	// draw sgimage resorce on gdi target
   402 	TDrawableSourceAndEquivRotatedBmps imageSource;
   403 	imageSource.iDrawableSrc = &source;
   404 	TPoint pos(20, 20);
   405 	TSize size(iGdiTarget->SizeInPixels());
   406 	size -= TSize(40, 40);
   407 	size.iWidth /= 2;
   408 	size.iHeight /= 2;
   409 	TSize size2(size);
   410 	size2 -= TSize(10, 10);
   411 
   412 	iGc->DrawResource(TRect(pos, size2), imageSource);
   413 	TESTNOERRORL(iGc->GetError());
   414 	iGc->DrawResource(TRect(pos+TPoint(size.iWidth, 0), size2), imageSource, DirectGdi::EGraphicsRotation90);
   415 	TESTNOERRORL(iGc->GetError());
   416 	iGc->DrawResource(TRect(pos+TPoint(0, size.iHeight), size2), imageSource, DirectGdi::EGraphicsRotation180);
   417 	TESTNOERRORL(iGc->GetError());
   418 	iGc->DrawResource(TRect(pos+size.AsPoint(), size2), imageSource, DirectGdi::EGraphicsRotation270);
   419 	TESTNOERRORL(iGc->GetError());
   420 
   421 	CleanupStack::PopAndDestroy(3, &image);
   422 	}
   423 
   424 /**
   425 Override of base class virtual
   426 @leave Gets system wide error code
   427 @return - TVerdict code
   428 */
   429 TVerdict CTInterleaving::doTestStepPreambleL()
   430 	{
   431 	CTDirectGdiStepBase::doTestStepPreambleL();	
   432 	return TestStepResult();
   433 	}
   434 	
   435 /** 
   436 Override of base class pure virtual
   437 Our implementation only gets called if the base class doTestStepPreambleL() did
   438 not leave. That being the case, the current test result value will be EPass.
   439 @leave Gets system wide error code
   440 @return TVerdict code
   441 */	
   442 TVerdict CTInterleaving::doTestStepL()
   443 	{
   444 	// Test for each target pixel format
   445 	for(TInt targetPixelFormatIndex = iTargetPixelFormatArray.Count() - 1; targetPixelFormatIndex >= 0 ; targetPixelFormatIndex--)
   446 		{
   447 		iTestParams.iTargetPixelFormat = iTargetPixelFormatArray[targetPixelFormatIndex];
   448 			
   449 		SetTargetL(iTestParams.iTargetPixelFormat, EOneContextOneTarget, TSize(400, 400));
   450 		RunTestsL();
   451 		}
   452 	CloseTMSGraphicsStep();
   453 	return TestStepResult();
   454 	}
   455 
   456 /**
   457 Override of base class virtual
   458 @leave Gets system wide error code
   459 @return - TVerdict code
   460 */
   461 TVerdict CTInterleaving::doTestStepPostambleL()
   462 	{
   463 	CTDirectGdiStepBase::doTestStepPostambleL();
   464 	return TestStepResult();
   465 	}
   466 
   467 /**
   468 Override of base class pure virtual
   469 Lists the tests to be run
   470 */
   471 void CTInterleaving::RunTestsL()
   472 	{
   473 	if(iUseDirectGdi)
   474 		{
   475 		SetTestStepID(_L("GRAPHICS-DIRECTGDI-INTERLEAVING-0001"));
   476 		TestSyncL();
   477 		RecordTestResultL();
   478 		SetTestStepID(_L("GRAPHICS-DIRECTGDI-INTERLEAVING-0002"));
   479 		TestAsyncL();
   480 		RecordTestResultL();
   481 		SetTestStepID(_L("GRAPHICS-DIRECTGDI-INTERLEAVING-0002"));
   482 		TestAsyncL(ETrue);
   483 		RecordTestResultL();
   484 		}
   485 	}