os/graphics/graphicscomposition/surfaceupdate/tsrc/tsurfaceupdateinteg.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 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 <e32std.h>
    17 #include <hal.h>
    18 #include <u32hal.h>
    19 #include <limits.h>
    20 #include <e32const.h>
    21 #include <graphics/surfaceupdateclient.h>
    22 #include <graphics/suerror.h>
    23 #include <graphics/wstestscreencapture.h>
    24 #include <graphics/testscreencapture.h>
    25 #include "surfaceupdatetest.h"
    26 #include "tsurfaceupdateinteg.h"
    27 #include "twindows.h"
    28 #include "tredrawhandler.h"
    29 #include "tsurfacehelper.h"
    30 
    31 const TSize windowSize(160, 100);
    32 const TSize windowHalfSize(windowSize.iWidth / 2, 100);
    33 const TPoint windowTopLeft(10,10);
    34 const TPoint windowTopMiddle(windowTopLeft.iX + windowSize.iWidth / 2, windowTopLeft.iY);
    35 
    36 
    37 CTSurfaceUpdateInteg::CTSurfaceUpdateInteg(CTestStep* aStep) :
    38 	CTGraphicsBase(aStep)
    39 	{
    40 	}
    41 
    42 CTSurfaceUpdateInteg::~CTSurfaceUpdateInteg()
    43 	{
    44 	iWindows.ResetAndDestroy();
    45 	iGroups.ResetAndDestroy();
    46 
    47 	iWsDevs.ResetAndDestroy();
    48 	iGcs.ResetAndDestroy();
    49 	
    50 	delete iRedrawHandler;
    51 	iSurfaceUpdate.Close();
    52 	delete iSurfaceHelper;
    53 	iBitmaps.ResetAndDestroy();
    54 
    55 	delete iGraphicsContext;
    56 	delete iBitmapDevice;
    57 	delete iRefBitmap;
    58 	
    59 	iWs.Close();
    60 	}
    61 
    62 /**
    63  * Create a screen device, drawing context and a window for each screen.
    64  * Create surfaces, open connection to the SUS.
    65  */
    66 void CTSurfaceUpdateInteg::ConstructL()
    67 	{
    68 	INFO_PRINTF1(_L("Test case construction"));
    69 	User::LeaveIfError(iWs.Connect());
    70 	iNumOfScreens = iWs.NumberOfScreens();
    71 	iSurfaceHelper = CSurfaceHelper::NewL();
    72 	const TInt stride = windowSize.iWidth * 4;
    73 	const TInt stride1 = windowHalfSize.iWidth * 4;
    74 	iSurface = iSurfaceHelper->CreateSurfaceL(windowSize, EUidPixelFormatXRGB_8888, stride,1);
    75 	iSurfaceDoubleBuffered = iSurfaceHelper->CreateSurfaceL(windowSize, EUidPixelFormatXRGB_8888, stride,2);
    76 	iSurfaceAbove = iSurfaceHelper->CreateSurfaceL(windowHalfSize, EUidPixelFormatXRGB_8888, stride1, 1);
    77 	iSurfaceAbove1 = iSurfaceHelper->CreateSurfaceL(windowSize, EUidPixelFormatXRGB_8888, stride, 1);
    78 	INFO_PRINTF1(_L("The surfaces have been created"));
    79 
    80 	iRefBitmap = new (ELeave)CFbsBitmap();
    81 	User::LeaveIfError(iRefBitmap->Create(windowSize,EColor16MU));
    82 	iBitmapDevice = CFbsBitmapDevice::NewL(iRefBitmap);
    83 	User::LeaveIfError(iBitmapDevice->CreateContext(iGraphicsContext));
    84 
    85 	//fill the whole surfaces with different color
    86 	iSurfaceHelper->FillRectangleL(iSurfaceAbove, TPoint(), windowHalfSize, KRgbYellow);
    87 	iSurfaceHelper->FillRectangleL(iSurfaceAbove1, TPoint(), windowSize, KRgbYellow);
    88 	iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbGreen);
    89 	iSurfaceHelper->FillRectangleL(iSurfaceDoubleBuffered, TPoint(), windowSize, KRgbCyan);
    90 	FillRefBitmap(KRgbGreen);
    91 	INFO_PRINTF1(_L("The surfaces and a reference bitmap have been filled with color"));
    92 	
    93 	User::LeaveIfError(iSurfaceUpdate.Connect());
    94 	
    95 	iRedrawHandler = new (ELeave) CTRedrawHandler(iWs); //will deal with all redrawing command
    96 	iRedrawHandler->Start();
    97 
    98 	//create windows and assign surfaces to them
    99 	for(TInt ii = 0; ii < 2; ii++)
   100 		{
   101 		CWsScreenDevice* wsDev = new (ELeave) CWsScreenDevice(iWs);
   102 		iWsDevs.AppendL(wsDev);
   103 		User::LeaveIfError(wsDev->Construct(ii));
   104 		CWindowGc* gc = NULL;
   105 		User::LeaveIfError(wsDev->CreateContext(gc));
   106 		iGcs.AppendL(gc);
   107 
   108 		CTWindowGroup* defaultGroup = CreateGroupL(wsDev);
   109 		CTWindow* windowSingle = CTWindow::NewL(iWs, *defaultGroup, *gc);
   110 		RegisterWindowL(windowSingle);
   111 		windowSingle->Window()->SetExtent(windowTopLeft, windowSize);
   112 		windowSingle->Window()->SetBackgroundSurface(iSurface);
   113 		windowSingle->Window()->Activate();
   114 		
   115 		CTWindow* windowDouble = CTWindow::NewL(iWs, *defaultGroup, *gc);
   116 		RegisterWindowL(windowDouble);
   117 		windowDouble->Window()->SetExtent(windowTopLeft, windowSize);
   118 		windowDouble->Window()->SetBackgroundSurface(iSurfaceDoubleBuffered);
   119 		windowDouble->Window()->SetVisible(EFalse);
   120 		windowDouble->Window()->Activate();
   121 
   122 		CTWindow* windowAbove = CTWindow::NewL(iWs, *iGroups[ii], *iGcs[ii]);
   123 		RegisterWindowL(windowAbove);
   124 		windowAbove->Window()->SetExtent(windowTopLeft, windowHalfSize);
   125 		windowAbove->Window()->SetBackgroundSurface(iSurfaceAbove);
   126 		windowAbove->Window()->SetVisible(EFalse);
   127 		windowAbove->Window()->Activate();
   128 		if(ii == 0)
   129 			{
   130 			iWindowAbove11 = CTWindow::NewL(iWs, *iGroups[ii], *iGcs[ii]);
   131 			RegisterWindowL(iWindowAbove11);
   132 			iWindowAbove11->Window()->SetExtent(windowTopLeft, windowSize);
   133 			iWindowAbove11->Window()->SetBackgroundSurface(iSurfaceAbove1);
   134 			iWindowAbove11->Window()->SetVisible(EFalse);
   135 			iWindowAbove11->Window()->Activate();
   136 
   137 			iWindowAbove1 = windowAbove;
   138 			iWindowSingleBuffured1 = windowSingle;
   139 			iWindowDoubleBuffured1 = windowDouble;
   140 			}
   141 		else
   142 			{
   143 			iWindowAbove2 = windowAbove;
   144 			iWindowSingleBuffured2 = windowSingle;
   145 			iWindowDoubleBuffured2 = windowDouble;
   146 			}
   147 
   148 	    TPixelsTwipsAndRotation sizeAndRotation;
   149 	    iWsDevs[ii]->GetDefaultScreenSizeAndRotation(sizeAndRotation);
   150 	    CFbsBitmap* bitmap = new (ELeave)CFbsBitmap();
   151 	    iBitmaps.AppendL(bitmap);
   152 	    User::LeaveIfError(bitmap->Create(sizeAndRotation.iPixelSize, EColor16MU));
   153         INFO_PRINTF4(_L("Bitmap with size: %d, %d was created to match the size of the screen %d"), sizeAndRotation.iPixelSize.iWidth, sizeAndRotation.iPixelSize.iHeight, ii);
   154 		}
   155 	INFO_PRINTF1(_L("The windows have been created"));
   156 	
   157 	iWs.Finish();
   158 	}
   159 
   160 /**
   161  * Create the window group for the given screen device and put it into the list.
   162  */
   163 CTWindowGroup* CTSurfaceUpdateInteg::CreateGroupL(CWsScreenDevice* aScreenDevice)
   164 	{
   165 	CTWindowGroup* group = CTWindowGroup::NewL(iWs, aScreenDevice);
   166 	CleanupStack::PushL(group);
   167 	iGroups.AppendL(group);
   168 	CleanupStack::Pop();
   169 	return group;
   170 	}
   171 
   172 /**
   173  * Append a window into the list for retrawing it and destroying in the future.
   174  */
   175 void CTSurfaceUpdateInteg::RegisterWindowL(CTWindowTreeNode* aWindow)
   176 	{
   177 	CleanupStack::PushL(aWindow);
   178 	iWindows.AppendL(aWindow);
   179 	CleanupStack::Pop(aWindow);
   180 	}
   181 
   182 /**
   183  * Go through all screens and compare the whole surface area with the reference bitmap.
   184  * 
   185  * @return ETrue, if the surface is exactly the same as the reference bitmap or EFalse otherwise. 
   186  */
   187 TBool CTSurfaceUpdateInteg::CompareAllScreens()
   188 	{
   189 	TBool res = ETrue;
   190 	TRect rc(windowTopLeft, windowSize);
   191 	for(TInt ii = 0; (ii < iNumOfScreens) && res; ii++)
   192 		{
   193 		res = Compare(ii, rc, iRefBitmap);
   194 		}
   195 	return res;
   196 	}
   197 
   198 /**
   199  * Compare part of the screen with the reference bitmap.
   200  * 
   201  * @param aScreenNumber Screen number.
   202  * @param aRectSrc The area of the screen to be compared.
   203  * @param aRefBitmap Bitmap for comparison.
   204  * @return ETrue, if given part of the screen is exactly the same as the reference bitmap or EFalse otherwise. 
   205  */
   206 TBool CTSurfaceUpdateInteg::Compare(TInt aScreenNumber, const TRect& aRectSrc, CFbsBitmap* aRefBitmap)
   207 	{
   208 	MTestScreenCapture* csc = static_cast<MTestScreenCapture*> (iWsDevs[aScreenNumber]->GetInterface(MTestScreenCapture::KUidTestScreenCaptureIf));
   209 	if(!csc) //shouldn't happen, as we have checked this before
   210 		{
   211 		return EFalse;
   212 		}
   213 	
   214 	TBool res = ETrue;
   215 	TInt ret = csc->ComposeScreen(*(iBitmaps[aScreenNumber]));
   216 	if(ret != KErrNone)
   217 		{
   218 		INFO_PRINTF2(_L("Composition screen failure, err = %d"), ret);
   219 		res = EFalse;
   220 		}
   221 	//Go through all pixels in screen bitmap for specified area and check that they are 
   222 	//identical to corresponding pixels in reference bitmap
   223 	for(TInt ii = 0; (ii < aRectSrc.Height()) && res; ii++)
   224 		{
   225 		for(TInt jj = 0; (jj < aRectSrc.Width()) && res; jj++)
   226 			{
   227 			TRgb refCol;
   228 			aRefBitmap->GetPixel(refCol, TPoint(jj, ii));
   229 			TRgb col;
   230 			(iBitmaps[aScreenNumber])->GetPixel(col, TPoint(jj, ii) + aRectSrc.iTl);
   231 			if(refCol != col)
   232 				{
   233 				res = EFalse;
   234 				}
   235 			}
   236 		}
   237 	//useful for debugging
   238 #ifdef TEST_COMPARE_PARTLY_UPDATED_SCREEN 	
   239 	if(!res)
   240 		{
   241 		iBitmap->Save(_L("c:\\bitmap.mbm"));
   242 		aRefBitmap->Save(_L("c:\\ref.mbm"));
   243 		}
   244 #endif
   245 	
   246 	return res;
   247 	}
   248 
   249 /**
   250  * Fill reference bitmap with color specified.
   251  * 
   252  */
   253 void CTSurfaceUpdateInteg::FillRefBitmap(TRgb aColor)
   254 	{
   255 	TRect rect = TRect(iRefBitmap->SizeInPixels());
   256 	iGraphicsContext->SetBrushColor(aColor);
   257 	iGraphicsContext->SetPenColor(aColor);
   258 	iGraphicsContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
   259 	iGraphicsContext->DrawRect(rect);
   260 	}
   261 
   262 /**
   263   @SYMTestCaseID  GRAPHIC-SURFACEUPDATE-0026
   264   	
   265   @SYMCR CR1650
   266 
   267   @SYMREQ REQ11596
   268 
   269   @SYMTestCaseDesc 
   270   	SubmitUpdate() to cope with Global Updates with surface on various 
   271   	screens when the dirty region to update may not be visible on all screens
   272 
   273   @SYMTestPriority High
   274 
   275   @SYMTestStatus Implemented
   276 	
   277   @SYMTestActions The test consists of a single surface, visible on 
   278   screens A (master), B.
   279 	1.	Submit a global update for the surface, passing a null dirty region.
   280 	2.	Submit a global update for the surface, passing a dirty region 
   281 	that is only visible on screens A  (that particular region for the 
   282 	surface is not visible on B).
   283 	3.	Submit a global update for the surface, passing a dirty region 
   284 	that is only visible on screens B (that particular region for the 
   285 	surface is not visible on A).
   286 	4.	Submit a global update for the surface, passing a dirty 
   287 	region that is not visible on any of the screens.
   288   
   289   @SYMTestExpectedResults 
   290   	1.	TRequestStatus signals KErrNone in all cases. Timestamps must 
   291   	be valid. The surface gets updated on all screens.
   292 	2.	TRequestStatus signals KErrNone in all cases. Timestamps must 
   293 	be valid. The surface gets updated only on screens A. Screen B is unchanged.
   294 	3.	TRequestStatus signals KErrNone in all cases. Timestamps must 
   295 	be valid. The surface gets updated only on screens B. 
   296 	Screen A is unchanged.
   297 	4.	SubmitUpdate() returns KErrNone.
   298 */
   299 void CTSurfaceUpdateInteg::TestCase1L()
   300 	{
   301 	INFO_PRINTF1(_L("Global Submit Update with/without update region supplied"));
   302 	
   303 	const TInt bufferNumber = 0; 
   304 	TRequestStatus status = KRequestPending;
   305 	TRequestStatus status1 = KRequestPending;
   306 	TRequestStatus status2 = KRequestPending;
   307 	TUint64 timestampComposition = 0;
   308 	TTimeStamp timeStamp; 
   309 	
   310 	//Fill the surface to different colour, submit update for the whole surface 
   311 	//and check that screen is updated correctly
   312 	INFO_PRINTF1(_L("Fill the surface with the blue color"));
   313 	iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbBlue);
   314 	FillRefBitmap(KRgbBlue);
   315 	
   316 	INFO_PRINTF1(_L("Updating the whole area of the surface"));
   317 	TUint64 timestampBefore = User::FastCounter();
   318 	iSurfaceUpdate.NotifyWhenAvailable(status);	
   319 	iSurfaceUpdate.NotifyWhenDisplayed(status1, timeStamp);	
   320 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(10, status2);
   321 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
   322 	User::WaitForRequest(status);
   323 	User::WaitForRequest(status1);
   324 	User::WaitForRequest(status2);
   325 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   326 
   327 	TUint64 timestampAfter = User::FastCounter();
   328 	if(timestampAfter < timestampBefore)
   329 		{
   330 		timestampAfter += UINT_MAX;
   331 		}
   332 	timestampComposition = timeStamp();
   333 	if(timestampComposition < timestampBefore)
   334 		{
   335 		timestampComposition += UINT_MAX;
   336 		}
   337 	
   338 	TEST(status == KErrNone);
   339 	TEST(status1 == KErrNone);
   340 	TEST(status2 == KErrNone);
   341 	TEST(timestampComposition != 0);
   342 	TEST(timestampAfter >= timestampComposition);
   343 	TEST(timestampBefore <= timestampComposition);
   344 	TEST(CompareAllScreens());
   345 
   346 	//Fill the surface to different colour; hide the part of the surface on 
   347 	//the screen which is not a master, submit update for the area of the surface 
   348 	//which is only visible on the master. Check that only master screen gets updated.
   349 	INFO_PRINTF1(_L("Hide the part of the surface on the second screen"));
   350 	iWindowAbove1->Window()->SetVisible(EFalse);
   351 	iWindowAbove2->Window()->SetVisible(ETrue);
   352 	iWs.Finish();
   353 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
   354 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   355 	
   356 	INFO_PRINTF1(_L("Fill the surface with the green color"));
   357 	iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbGreen);
   358 	
   359 	TRect rc(windowHalfSize);
   360 	rc.Shrink(10, 10);
   361 	RRegion region(1, &rc); //this area is hidden if the window above is visible
   362 	timestampBefore = User::FastCounter();
   363 	iSurfaceUpdate.NotifyWhenAvailable(status);	
   364 	iSurfaceUpdate.NotifyWhenDisplayed(status1, timeStamp);	
   365 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(10, status2);
   366 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber, &region);
   367 	User::WaitForRequest(status);
   368 	User::WaitForRequest(status1);
   369 	User::WaitForRequest(status2);
   370 	User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
   371 
   372 	timestampAfter = User::FastCounter();
   373 	if(timestampAfter < timestampBefore)
   374 		{
   375 		timestampAfter += UINT_MAX;
   376 		}
   377 	timestampComposition = timeStamp();
   378 	if(timestampComposition < timestampBefore)
   379 		{
   380 		timestampComposition += UINT_MAX;
   381 		}
   382 	
   383 	TEST(status == KErrNone);
   384 	TEST(status1 == KErrNone);
   385 	TEST(status2 == KErrNone);
   386 	TEST(timestampComposition != 0);
   387 	TEST(timestampAfter >= timestampComposition);
   388 	TEST(timestampBefore <= timestampComposition);
   389 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   390 
   391 	//first screen should be updated, as the surface is visible here
   392 	TRect rectSrc = rc;
   393 	rectSrc.Move(windowTopLeft);
   394 	FillRefBitmap(KRgbGreen);
   395 	TEST(Compare(0, rectSrc, iRefBitmap));
   396 	//check that second screen doesn't update visible part of the surface 
   397 	FillRefBitmap(KRgbYellow);
   398 	TEST(Compare(1, rectSrc, iRefBitmap));
   399 
   400 	//Fill the surface to different colour; hide the part of the surface 
   401 	//on the master screen, submit update for the area of the surface 
   402 	//which is only visible on non-master. Check that only non-master screen gets updated.
   403 	INFO_PRINTF1(_L("Hide the part of the surface on the first screen"));
   404 	iWindowAbove1->Window()->SetVisible(ETrue);
   405 	iWindowAbove2->Window()->SetVisible(EFalse);
   406 	iWs.Finish();
   407 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   408 	
   409 	INFO_PRINTF1(_L("Fill the surface with the blue color"));
   410 	iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbBlue);
   411 	
   412 	timestampBefore = User::FastCounter();
   413 	iSurfaceUpdate.NotifyWhenAvailable(status);	
   414 	iSurfaceUpdate.NotifyWhenDisplayed(status1, timeStamp);	
   415 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(10, status2);
   416 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber, &region);
   417 	User::WaitForRequest(status);
   418 	User::WaitForRequest(status1);
   419 	User::WaitForRequest(status2);
   420 	User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
   421 
   422 	timestampAfter = User::FastCounter();
   423 	if(timestampAfter < timestampBefore)
   424 		{
   425 		timestampAfter += UINT_MAX;
   426 		}
   427 	timestampComposition = timeStamp();
   428 	if(timestampComposition < timestampBefore)
   429 		{
   430 		timestampComposition += UINT_MAX;
   431 		}
   432 	
   433 	TEST(status == KErrNone);
   434 	TEST(status1 == KErrNone);
   435 	TEST(status2 == KErrNone);
   436 	TEST(timestampComposition != 0);
   437 	TEST(timestampAfter >= timestampComposition);
   438 	TEST(timestampBefore <= timestampComposition);
   439 
   440 	//check that first screen doesn't update visible part of the surface 
   441 	FillRefBitmap(KRgbYellow);
   442 	TEST(Compare(0, rectSrc, iRefBitmap));
   443 	//second screen should be updated, as the surface is visible here
   444 	FillRefBitmap(KRgbBlue);
   445 	TEST(Compare(1, rectSrc, iRefBitmap));
   446 	
   447 	//Fill the surface to different colour; hide the part of the surface on the master screen, 
   448 	//submit update for the area of the surface which is not visible on any screen. 
   449 	//Check that all screens have not been updated.
   450 	INFO_PRINTF1(_L("Hide partly the surface on two screens"));
   451 	iWindowAbove1->Window()->SetVisible(ETrue);
   452 	iWindowAbove2->Window()->SetVisible(ETrue);
   453 	iWs.Finish();
   454 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
   455 	User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
   456 	
   457 	INFO_PRINTF1(_L("Fill the surface with the green color"));
   458 	iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbGreen);
   459 	FillRefBitmap(KRgbGreen);
   460 	
   461 	timestampBefore = User::FastCounter();
   462 	iSurfaceUpdate.NotifyWhenAvailable(status);	
   463 	iSurfaceUpdate.NotifyWhenDisplayed(status1, timeStamp);	
   464 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(10, status2);
   465 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber, &region);
   466 	User::WaitForRequest(status);
   467 	User::WaitForRequest(status1);
   468 	User::WaitForRequest(status2);
   469 	User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
   470 
   471 	timestampAfter = User::FastCounter();
   472 	if(timestampAfter < timestampBefore)
   473 		{
   474 		timestampAfter += UINT_MAX;
   475 		}
   476 	timestampComposition = timeStamp();
   477 	if(timestampComposition < timestampBefore)
   478 		{
   479 		timestampComposition += UINT_MAX;
   480 		}
   481 	
   482 	TEST(status == KErrNone);
   483 	TEST(status1 == KErrNone);
   484 	TEST(status2 == KErrNone);
   485 	TEST(timestampComposition != 0);
   486 	TEST(timestampAfter >= timestampComposition);
   487 	TEST(timestampBefore <= timestampComposition);
   488 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   489 	
   490 	//both first and second screen shouldn't be updated, as the surface is not visible here
   491 	FillRefBitmap(KRgbYellow);
   492 	TEST(Compare(0, rectSrc, iRefBitmap));
   493 	TEST(Compare(1, rectSrc, iRefBitmap));
   494 
   495 	INFO_PRINTF1(_L("Return to the initial state"));
   496 	iWindowAbove1->Window()->SetVisible(EFalse);
   497 	iWindowAbove2->Window()->SetVisible(EFalse);
   498 	iWs.Finish();
   499 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
   500 	User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
   501 	
   502 	FillRefBitmap(KRgbGreen);
   503 	TEST(CompareAllScreens());
   504 	}
   505 
   506 /**
   507   @SYMTestCaseID GRAPHIC-SURFACEUPDATE-0031
   508 
   509   @SYMCR CR1650
   510 
   511   @SYMREQ REQ11598
   512 
   513   @SYMTestCaseDesc NotifyWhenAvailable() to deal with global updates and be signalled 
   514  	correctly when screen is unplugged.
   515  	
   516   @SYMTestPriority 	High
   517 
   518   @SYMTestStatus Implemented
   519 	
   520   @SYMTestActions 
   521  	The test consists of a double-buffered surface, visible on screens A 
   522  	(master) and B,
   523 	1	Make global submit update with notify when available for the buffer 1.
   524 	2	Unplug screen A (notification is still in a progress )
   525 	3	Make global submit update with notify when available for the 
   526 	buffer 2 to trigger notification.
   527 	4	Make global submit update with notify when available for the 
   528 	buffer 1.
   529 	5	Plug in screen A. (notification is still in a progress )
   530 	6	Make global submit update with notify when available for 
   531 	the buffer 2.
   532   
   533   @SYMTestExpectedResults 
   534   	After step 3, notification is received with KErrNone (this is 
   535   	triggered by the Receiver for screen B).
   536 	After step 6, notification is received with KErrNone (this is 
   537 	triggered by the Receiver for screen A).
   538 */
   539 void CTSurfaceUpdateInteg::TestCase2L()
   540 	{
   541 	INFO_PRINTF1(_L("Exercising NotifyWhenAvailable while some screens are disconnected."));
   542 
   543 	//hide single-buffered surface and show a double buffered-surface
   544 	iWindowSingleBuffured1->Window()->SetVisible(EFalse);
   545 	iWindowSingleBuffured2->Window()->SetVisible(EFalse);
   546 	iWindowDoubleBuffured1->Window()->SetVisible(ETrue);
   547 	iWindowDoubleBuffured2->Window()->SetVisible(ETrue);
   548 	iWs.Finish();
   549 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   550 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceDoubleBuffered, 0);
   551 	FillRefBitmap(KRgbCyan);
   552 	TEST(CompareAllScreens());
   553 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   554 	
   555 	INFO_PRINTF1(_L("Fill the surface with the blue color"));
   556 	iSurfaceHelper->FillRectangleL(iSurfaceDoubleBuffered, TPoint(), windowSize, KRgbBlue);
   557 	
   558 	INFO_PRINTF1(_L("Disconnect the screen while notify when available request is still in a progress")); 
   559 	TRequestStatus status;
   560 	TSwitchDisplayAndReleaseBuffer param;
   561 	param.iBuffer = 0;
   562 	param.iScreen = 0;
   563 	param.iSurfaceId=iSurfaceDoubleBuffered;
   564 	CCommandDispatcher commandDispatcher(CCommandDispatcher::EDisconnectDisplayAndReleaseBuffer, &param);
   565 	
   566 	//Command dispatcher will be running in the separate thread. 
   567 	//The requirement for this caused by the fact that for dubble-buffered surfaces 
   568 	//the content update receiver will postpone completion of the request for availability until 
   569 	//client sends SubmitUpdate for another buffer. 
   570 	iSurfaceUpdate.NotifyWhenAvailable(status);	
   571 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceDoubleBuffered, 1);
   572 	TInt res = commandDispatcher.Start();  //kickoff another thread, which SubmitUpdate 
   573 											//for buffer 1 and disconnects the first screen
   574 	TEST(res == KErrNone);
   575 	User::WaitForRequest(status);//At that point we are blocked until command dispatcher sends SubmitUpdate for the buffer number 1
   576 	TEST(status == KErrNone);
   577 	
   578 	//connect the screen
   579 	INFO_PRINTF1(_L("Connect the screen while notify when available request is still in a progress")); 
   580 	CCommandDispatcher commandDispatcher1(CCommandDispatcher::EConnectDisplayAndReleaseBuffer, &param);
   581 	iSurfaceUpdate.NotifyWhenAvailable(status);	
   582 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceDoubleBuffered, 0);
   583 	res = commandDispatcher.Start();//kickoff another thread, which SubmitUpdate 
   584 										//for buffer 1 and connects the first screen
   585 
   586 	TEST(res == KErrNone);
   587 	User::WaitForRequest(status);
   588 	TEST(status == KErrNone);
   589 
   590 	//restore the original state
   591 	iWindowSingleBuffured1->Window()->SetVisible(ETrue);
   592 	iWindowSingleBuffured2->Window()->SetVisible(ETrue);
   593 	iWindowDoubleBuffured1->Window()->SetVisible(EFalse);
   594 	iWindowDoubleBuffured2->Window()->SetVisible(EFalse);
   595 	iWs.Finish();
   596 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   597 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceDoubleBuffered, 0);
   598 	FillRefBitmap(KRgbGreen);
   599 	TEST(CompareAllScreens());
   600 	}
   601 
   602 /**
   603   @SYMTestCaseID GRAPHIC-SURFACEUPDATE-0032
   604   	
   605   @SYMCR CR1650
   606 
   607   @SYMREQ REQ11599, REQ11600, REQ11601
   608 
   609   @SYMTestCaseDesc NotifyWhenDisplayedXTimes() to deal with global 
   610   updates and be signalled correctly when screen is unplugged.
   611 	
   612   @SYMTestPriority 	High
   613 
   614   @SYMTestStatus Implemented
   615 	
   616   @SYMTestActions 
   617   	The test consists of a single-buffered surface, S1, visible on 
   618   	screens A (master) and B.
   619 
   620 	Screens are ordered in the following priority: A > B
   621 		1	Make global submit update for surface S1 with notify 
   622 		when notify when displayed X times. X should be approximately 10 
   623 		seconds.
   624 		2	Unplug screen A while display XTimes is still in progress.
   625 		3	After receiving notification, plug in screen A
   626 		4	Make global submit update with notify when displayed X times. 
   627 		X should be approximately 10 seconds.
   628 		5	Make global submit update for surface S1, with notify when 
   629 		displayed X times. X should be approximately 10 seconds.
   630 		6	Unplug screen B while display XTimes is still in progress.
   631         7   Make global submit update for surface S1, with notify when 
   632         displayed X times. X should be approximately 10 seconds.		
   633 		8	Unplug screen A as well whilst display XTimes is still in progress.
   634 		9   Reconnect both screens
   635   	
   636   @SYMTestExpectedResults
   637   	After the 10 seconds have elapsed from step 1, notification is 
   638   	received (step 3) with KErrNone (this is triggered by the Receiver 
   639   	for screen B).
   640 	After 10 seconds have elapsed from step 4, notification is received 
   641 	with KErrNone (this is triggered by the Receiver for screen A).
   642 	After step 8 (which must occur before 10 seconds) notification will 
   643 	be received with KErrNotVisible (ie. The surface is not visible on 
   644 	any screen).
   645 */
   646 void CTSurfaceUpdateInteg::TestCase3()
   647 	{
   648 	INFO_PRINTF1(_L("Exercising NotifyWhenDisplayedXTimes while some screen is disconnected."));
   649 
   650 	TRequestStatus status;
   651 	TInt count = 100 * 2; 
   652 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(count, status);	
   653 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   654 	
   655 	INFO_PRINTF1(_L("Disconnect the screen when notification when displayed X times request is still in a progress")); 
   656 	TInt displayState = EDisconnect;
   657 	TInt disconnectedScreenNo = 0;
   658 	TInt res = UserSvr::HalFunction(EHalGroupDisplay | (disconnectedScreenNo<<16), EDisplayHalSetDisplayState, &displayState, NULL);
   659 	TEST(res == KErrNone);
   660 	User::WaitForRequest(status); //The content update receiver will complete notification when “count” number of display refreshes has occurred.  
   661 									//We are not blocked here indefinitely, so there is no point to use a command dispatcher
   662 	TEST(status == KErrNone);
   663 
   664 	//restore the first screen 
   665 	INFO_PRINTF1(_L("Connect the screen when notification when displayed X times request is still in a progress")); 
   666 	displayState = ENormalResolution;
   667 	res = UserSvr::HalFunction(EHalGroupDisplay | (disconnectedScreenNo<<16), EDisplayHalSetDisplayState, &displayState, NULL);
   668 	TEST(res == KErrNone);
   669 
   670 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(count, status);	
   671 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   672 	User::WaitForRequest(status);
   673 	TEST(status == KErrNone);
   674 	
   675 	// Make sure other surface is not visible
   676 	iWindowAbove11->Window()->SetVisible(EFalse);
   677 	iWs.Finish();
   678 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   679 	
   680 	// above1 surface should not be visible because window is not visible
   681 	TTimeStamp timeStamp; 
   682 	iSurfaceUpdate.NotifyWhenDisplayed(status, timeStamp);	
   683 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceAbove1, 0);
   684 	User::WaitForRequest(status);
   685 	TEST(status == KErrNotVisible);
   686 	
   687 	//disconnect the secondary screen - surface still visible on primary
   688 	INFO_PRINTF1(_L("Disconnect the secondary screen - surface still visible on primary")); 
   689 	displayState = EDisconnect;
   690 	disconnectedScreenNo = 1;
   691 	iSurfaceUpdate.NotifyWhenDisplayedXTimes(count, status);	
   692 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   693 	
   694 	res = UserSvr::HalFunction(EHalGroupDisplay | (disconnectedScreenNo<<16), EDisplayHalSetDisplayState, &displayState, NULL);
   695 	TEST(res == KErrNone);
   696 	User::WaitForRequest(status);
   697 	TEST(status == KErrNone);
   698 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   699 
   700    //disconnect the primary screen - surface now not visible on any screen
   701     INFO_PRINTF1(_L("Disconnect the primary screen - surface not visible on any screen")); 
   702     displayState = EDisconnect;
   703     disconnectedScreenNo = 0;
   704     iSurfaceUpdate.NotifyWhenDisplayedXTimes(count, status);    
   705     iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   706     
   707     res = UserSvr::HalFunction(EHalGroupDisplay | (disconnectedScreenNo<<16), EDisplayHalSetDisplayState, &displayState, NULL);
   708     TEST(res == KErrNone);
   709     User::WaitForRequest(status);
   710     TEST(status == KErrNotVisible); // not visible raised if primary is disconnected
   711     User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   712         
   713 
   714     //restore initial state 
   715     disconnectedScreenNo = 0;
   716     displayState = ENormalResolution;
   717     res = UserSvr::HalFunction(EHalGroupDisplay | (disconnectedScreenNo<<16), EDisplayHalSetDisplayState, &displayState, NULL);
   718     TEST(res == KErrNone);
   719     disconnectedScreenNo = 1;
   720     res = UserSvr::HalFunction(EHalGroupDisplay | (disconnectedScreenNo<<16), EDisplayHalSetDisplayState, &displayState, NULL);
   721     TEST(res == KErrNone);
   722 
   723     
   724 	iWs.Finish();	
   725 	iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
   726 	User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
   727 	TEST(CompareAllScreens());
   728 	}
   729 
   730 void CTSurfaceUpdateInteg::RunTestCaseL(TInt aCurTestCase)
   731 	{
   732 	((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
   733 	switch(aCurTestCase)
   734 		{
   735 	case 1:
   736 		{
   737 		
   738 		if((static_cast <CTSurfaceUpdateIntegStep*> (iStep)) -> IsScreenCaptureSupported()  && (iNumOfScreens > 1))
   739 			{
   740 			((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(_L("GRAPHIC-SURFACEUPDATE-0026"));
   741 			INFO_PRINTF1(_L("TestCase1"));
   742 			TestCase1L();
   743 			}
   744 		else
   745 			{
   746 			((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
   747 			INFO_PRINTF3(_L("The test will be skipped as the environment is not ready: Number of screen : %d, Is screen capture supported: %d"), 
   748 					iNumOfScreens, (static_cast <CTSurfaceUpdateIntegStep*> (iStep)) -> IsScreenCaptureSupported());
   749 			TestComplete();		
   750 			}	
   751 		break;
   752 		}
   753 #ifdef __WINS__
   754 	case 2:
   755 		{
   756 		((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(_L("GRAPHIC-SURFACEUPDATE-0031"));
   757 		INFO_PRINTF1(_L("TestCase2"));
   758 		TestCase2L();
   759 		break;
   760 		}
   761 	case 3:
   762 		{
   763 		((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(_L("GRAPHIC-SURFACEUPDATE-0032"));
   764 		INFO_PRINTF1(_L("TestCase3"));
   765 		TestCase3();
   766 		break;
   767 		}
   768 #endif		
   769 	default:
   770 		((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
   771 		((CTSurfaceUpdateIntegStep*)iStep)->CloseTMSGraphicsStep();
   772 		TestComplete();		
   773 		break;
   774 		}
   775 	((CTSurfaceUpdateIntegStep*)iStep)->RecordTestResultL();
   776 	}
   777 //--------------
   778 _LIT(KCommandDispatcher, "CommandDispatcher");
   779 const TUint KDefaultHeapSize=0x10000;
   780 
   781 /**
   782  * Launch the command thread.
   783  */
   784 TInt CCommandDispatcher::Start()
   785 	{
   786 	RThread commandThread;
   787 	TInt res = KErrGeneral;
   788 	TBuf<64> commandThreadName;
   789 	TBuf<64> commandThreaMask;
   790 	
   791 	// Guarantee uniqueness of thread name by using timestamp
   792 	TTime tm;
   793 	TBuf<32> timeStamp;
   794 	tm.UniversalTime();
   795 	TRAP(res, tm.FormatL(timeStamp, _L("_%H%T%S%C")));
   796 	if(res != KErrNone)
   797 		{
   798 		return res;
   799 		}
   800 
   801 	commandThreadName.Append(KCommandDispatcher);
   802 	commandThreadName.Append(timeStamp);
   803 	commandThreaMask = commandThreadName;
   804 	commandThreaMask.Insert(0, _L("*"));
   805 	TFindThread findThread(commandThreaMask);
   806 	TFullName name;
   807 	  // Need to check that the thread exists.
   808 	if (findThread.Next(name)!=KErrNone)
   809 		{
   810 		  // Create the thread for the server.
   811 		res = commandThread.Create(commandThreadName,
   812 			CCommandDispatcher::ThreadFunction,
   813 			KDefaultStackSize,
   814 			KDefaultHeapSize,
   815 			KDefaultHeapSize,
   816 			this
   817 			);
   818 			
   819           // The thread has been created OK so get it started - however
   820           // we need to make sure that it has started before we continue.
   821 		if (res==KErrNone)
   822 			{
   823 			TRequestStatus rendezvousStatus;
   824 			commandThread.SetPriority(EPriorityNormal);
   825 			commandThread.Rendezvous(rendezvousStatus);
   826 			commandThread.Resume();
   827 			}
   828 		}
   829 	commandThread.Close();
   830 	return res;
   831 	}
   832 
   833 TInt CCommandDispatcher::ThreadFunction(TAny* aAny)
   834 	{
   835 	  // get clean-up stack
   836 	CTrapCleanup* cleanup=CTrapCleanup::New();
   837 	CCommandDispatcher* commandDispatcher = (CCommandDispatcher*) aAny;
   838 	TRAPD(res, commandDispatcher->ExecuteCommandL());
   839 	delete cleanup; 
   840 	return res;
   841 	}
   842 
   843 /**
   844  * Run commands in a thread different to the thread where the instance 
   845  * of the class was initialized.
   846  */
   847 void CCommandDispatcher::ExecuteCommandL()
   848 	{
   849 	switch(iCommandName)
   850 		{
   851 	case EDisconnectDisplayAndReleaseBuffer:
   852 		{
   853 		RSurfaceUpdateSession surfaceUpdate;
   854 		User::LeaveIfError(surfaceUpdate.Connect());
   855 		CleanupClosePushL(surfaceUpdate);
   856 		TSwitchDisplayAndReleaseBuffer* param = static_cast<TSwitchDisplayAndReleaseBuffer*>(iParam); 
   857 		if(!param)
   858 			{
   859 			User::Leave(KErrArgument);
   860 			}
   861 		TInt displayState = EDisconnect;
   862 		TInt screenNumber = param->iScreen;
   863 		TInt bufferNumber = param->iBuffer;
   864 		User::LeaveIfError(UserSvr::HalFunction(EHalGroupDisplay | (screenNumber<<16), EDisplayHalSetDisplayState, &displayState, NULL));
   865 		//Submit Update to unblock the main client thread 
   866 		User::LeaveIfError(surfaceUpdate.SubmitUpdate(KAllScreens, param->iSurfaceId, bufferNumber));
   867 		CleanupStack::PopAndDestroy(&surfaceUpdate);
   868 		break;
   869 		}
   870 	case EConnectDisplayAndReleaseBuffer:
   871 		{
   872 		RSurfaceUpdateSession surfaceUpdate;
   873 		User::LeaveIfError(surfaceUpdate.Connect());
   874 		CleanupClosePushL(surfaceUpdate);
   875 		TSwitchDisplayAndReleaseBuffer* param = static_cast<TSwitchDisplayAndReleaseBuffer*>(iParam); 
   876 		if(!param)
   877 			{
   878 			User::Leave(KErrArgument);
   879 			}
   880 		TInt displayState = ENormalResolution;
   881 		TInt screenNumber = param->iScreen;
   882 		TInt bufferNumber = param->iBuffer;
   883 		User::LeaveIfError(UserSvr::HalFunction(EHalGroupDisplay | (screenNumber<<16), EDisplayHalSetDisplayState, &displayState, NULL));
   884 		//Submit Update to unblock the main client thread 
   885 		User::LeaveIfError(surfaceUpdate.SubmitUpdate(KAllScreens, param->iSurfaceId, bufferNumber));
   886 		CleanupStack::PopAndDestroy(&surfaceUpdate);
   887 		break;
   888 		}
   889 	default:
   890 		User::Leave(KErrNotSupported);
   891 		break;
   892 		}
   893 	}
   894 
   895 //--------------
   896 __CONSTRUCT_STEP__(SurfaceUpdateInteg)
   897 
   898 /**
   899  * Retrieve screen capturing plug-in, if succeed set a flag.
   900  */
   901 void CTSurfaceUpdateIntegStep::TestSetupL()
   902 	{
   903 //	check if the screen capture plug-in presents in the system
   904 	RWsSession ws;
   905 	User::LeaveIfError(ws.Connect());
   906 	CleanupClosePushL(ws);
   907 
   908 	TInt numOfScreens = ws.NumberOfScreens();
   909 	if(numOfScreens < 2)
   910 		{
   911 		ERR_PRINTF2(_L("Environment is not ready, the number of the screens in the system for this test should be 2 or more, the current number is: %d"), numOfScreens);
   912 		User::Leave(KErrNotReady);
   913 		}
   914 	
   915 	CWsScreenDevice* wsDev = new (ELeave) CWsScreenDevice(ws);
   916 	CleanupStack::PushL(wsDev);
   917 	User::LeaveIfError(wsDev->Construct(0));
   918 	TDisplayMode dispMode = wsDev->DisplayMode();
   919 	INFO_PRINTF2(_L("Screen device display mode is: %d."), dispMode);
   920 	
   921 	MTestScreenCapture* csc = static_cast<MTestScreenCapture*> (wsDev->GetInterface(MTestScreenCapture::KUidTestScreenCaptureIf));
   922 	if(csc)
   923 		{
   924 		INFO_PRINTF1(_L("Screen capture plug-in presents in the system."));
   925 		iScreenCapture = ETrue;
   926 		}
   927 	else
   928 		{
   929 		INFO_PRINTF1(_L("Screen capture plug-in is not installed in the system, to make automated checking screen capture rendering stage is required, \
   930 see graphics\\wserv_std_plugins\\screencapture"));
   931 		}
   932 	
   933 	CleanupStack::PopAndDestroy(2, &ws); //ws, wsDev
   934 	}
   935 	
   936 void CTSurfaceUpdateIntegStep::TestClose()
   937 	{
   938 	}
   939