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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
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"
28 #include "tredrawhandler.h"
29 #include "tsurfacehelper.h"
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);
37 CTSurfaceUpdateInteg::CTSurfaceUpdateInteg(CTestStep* aStep) :
42 CTSurfaceUpdateInteg::~CTSurfaceUpdateInteg()
44 iWindows.ResetAndDestroy();
45 iGroups.ResetAndDestroy();
47 iWsDevs.ResetAndDestroy();
48 iGcs.ResetAndDestroy();
50 delete iRedrawHandler;
51 iSurfaceUpdate.Close();
52 delete iSurfaceHelper;
53 iBitmaps.ResetAndDestroy();
55 delete iGraphicsContext;
63 * Create a screen device, drawing context and a window for each screen.
64 * Create surfaces, open connection to the SUS.
66 void CTSurfaceUpdateInteg::ConstructL()
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"));
80 iRefBitmap = new (ELeave)CFbsBitmap();
81 User::LeaveIfError(iRefBitmap->Create(windowSize,EColor16MU));
82 iBitmapDevice = CFbsBitmapDevice::NewL(iRefBitmap);
83 User::LeaveIfError(iBitmapDevice->CreateContext(iGraphicsContext));
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"));
93 User::LeaveIfError(iSurfaceUpdate.Connect());
95 iRedrawHandler = new (ELeave) CTRedrawHandler(iWs); //will deal with all redrawing command
96 iRedrawHandler->Start();
98 //create windows and assign surfaces to them
99 for(TInt ii = 0; ii < 2; ii++)
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));
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();
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();
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();
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();
137 iWindowAbove1 = windowAbove;
138 iWindowSingleBuffured1 = windowSingle;
139 iWindowDoubleBuffured1 = windowDouble;
143 iWindowAbove2 = windowAbove;
144 iWindowSingleBuffured2 = windowSingle;
145 iWindowDoubleBuffured2 = windowDouble;
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);
155 INFO_PRINTF1(_L("The windows have been created"));
161 * Create the window group for the given screen device and put it into the list.
163 CTWindowGroup* CTSurfaceUpdateInteg::CreateGroupL(CWsScreenDevice* aScreenDevice)
165 CTWindowGroup* group = CTWindowGroup::NewL(iWs, aScreenDevice);
166 CleanupStack::PushL(group);
167 iGroups.AppendL(group);
173 * Append a window into the list for retrawing it and destroying in the future.
175 void CTSurfaceUpdateInteg::RegisterWindowL(CTWindowTreeNode* aWindow)
177 CleanupStack::PushL(aWindow);
178 iWindows.AppendL(aWindow);
179 CleanupStack::Pop(aWindow);
183 * Go through all screens and compare the whole surface area with the reference bitmap.
185 * @return ETrue, if the surface is exactly the same as the reference bitmap or EFalse otherwise.
187 TBool CTSurfaceUpdateInteg::CompareAllScreens()
190 TRect rc(windowTopLeft, windowSize);
191 for(TInt ii = 0; (ii < iNumOfScreens) && res; ii++)
193 res = Compare(ii, rc, iRefBitmap);
199 * Compare part of the screen with the reference bitmap.
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.
206 TBool CTSurfaceUpdateInteg::Compare(TInt aScreenNumber, const TRect& aRectSrc, CFbsBitmap* aRefBitmap)
208 MTestScreenCapture* csc = static_cast<MTestScreenCapture*> (iWsDevs[aScreenNumber]->GetInterface(MTestScreenCapture::KUidTestScreenCaptureIf));
209 if(!csc) //shouldn't happen, as we have checked this before
215 TInt ret = csc->ComposeScreen(*(iBitmaps[aScreenNumber]));
218 INFO_PRINTF2(_L("Composition screen failure, err = %d"), ret);
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++)
225 for(TInt jj = 0; (jj < aRectSrc.Width()) && res; jj++)
228 aRefBitmap->GetPixel(refCol, TPoint(jj, ii));
230 (iBitmaps[aScreenNumber])->GetPixel(col, TPoint(jj, ii) + aRectSrc.iTl);
237 //useful for debugging
238 #ifdef TEST_COMPARE_PARTLY_UPDATED_SCREEN
241 iBitmap->Save(_L("c:\\bitmap.mbm"));
242 aRefBitmap->Save(_L("c:\\ref.mbm"));
250 * Fill reference bitmap with color specified.
253 void CTSurfaceUpdateInteg::FillRefBitmap(TRgb aColor)
255 TRect rect = TRect(iRefBitmap->SizeInPixels());
256 iGraphicsContext->SetBrushColor(aColor);
257 iGraphicsContext->SetPenColor(aColor);
258 iGraphicsContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
259 iGraphicsContext->DrawRect(rect);
263 @SYMTestCaseID GRAPHIC-SURFACEUPDATE-0026
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
273 @SYMTestPriority High
275 @SYMTestStatus Implemented
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.
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.
299 void CTSurfaceUpdateInteg::TestCase1L()
301 INFO_PRINTF1(_L("Global Submit Update with/without update region supplied"));
303 const TInt bufferNumber = 0;
304 TRequestStatus status = KRequestPending;
305 TRequestStatus status1 = KRequestPending;
306 TRequestStatus status2 = KRequestPending;
307 TUint64 timestampComposition = 0;
308 TTimeStamp timeStamp;
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);
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
327 TUint64 timestampAfter = User::FastCounter();
328 if(timestampAfter < timestampBefore)
330 timestampAfter += UINT_MAX;
332 timestampComposition = timeStamp();
333 if(timestampComposition < timestampBefore)
335 timestampComposition += UINT_MAX;
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());
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);
353 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
354 User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
356 INFO_PRINTF1(_L("Fill the surface with the green color"));
357 iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbGreen);
359 TRect rc(windowHalfSize);
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, ®ion);
367 User::WaitForRequest(status);
368 User::WaitForRequest(status1);
369 User::WaitForRequest(status2);
370 User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
372 timestampAfter = User::FastCounter();
373 if(timestampAfter < timestampBefore)
375 timestampAfter += UINT_MAX;
377 timestampComposition = timeStamp();
378 if(timestampComposition < timestampBefore)
380 timestampComposition += UINT_MAX;
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
391 //first screen should be updated, as the surface is visible here
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));
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);
407 User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
409 INFO_PRINTF1(_L("Fill the surface with the blue color"));
410 iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbBlue);
412 timestampBefore = User::FastCounter();
413 iSurfaceUpdate.NotifyWhenAvailable(status);
414 iSurfaceUpdate.NotifyWhenDisplayed(status1, timeStamp);
415 iSurfaceUpdate.NotifyWhenDisplayedXTimes(10, status2);
416 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber, ®ion);
417 User::WaitForRequest(status);
418 User::WaitForRequest(status1);
419 User::WaitForRequest(status2);
420 User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
422 timestampAfter = User::FastCounter();
423 if(timestampAfter < timestampBefore)
425 timestampAfter += UINT_MAX;
427 timestampComposition = timeStamp();
428 if(timestampComposition < timestampBefore)
430 timestampComposition += UINT_MAX;
433 TEST(status == KErrNone);
434 TEST(status1 == KErrNone);
435 TEST(status2 == KErrNone);
436 TEST(timestampComposition != 0);
437 TEST(timestampAfter >= timestampComposition);
438 TEST(timestampBefore <= timestampComposition);
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));
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);
454 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
455 User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
457 INFO_PRINTF1(_L("Fill the surface with the green color"));
458 iSurfaceHelper->FillRectangleL(iSurface, TPoint(), windowSize, KRgbGreen);
459 FillRefBitmap(KRgbGreen);
461 timestampBefore = User::FastCounter();
462 iSurfaceUpdate.NotifyWhenAvailable(status);
463 iSurfaceUpdate.NotifyWhenDisplayed(status1, timeStamp);
464 iSurfaceUpdate.NotifyWhenDisplayedXTimes(10, status2);
465 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber, ®ion);
466 User::WaitForRequest(status);
467 User::WaitForRequest(status1);
468 User::WaitForRequest(status2);
469 User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
471 timestampAfter = User::FastCounter();
472 if(timestampAfter < timestampBefore)
474 timestampAfter += UINT_MAX;
476 timestampComposition = timeStamp();
477 if(timestampComposition < timestampBefore)
479 timestampComposition += UINT_MAX;
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
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));
495 INFO_PRINTF1(_L("Return to the initial state"));
496 iWindowAbove1->Window()->SetVisible(EFalse);
497 iWindowAbove2->Window()->SetVisible(EFalse);
499 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, bufferNumber);
500 User::After(TTimeIntervalMicroSeconds32(1000000)); //useful for visual checking
502 FillRefBitmap(KRgbGreen);
503 TEST(CompareAllScreens());
507 @SYMTestCaseID GRAPHIC-SURFACEUPDATE-0031
513 @SYMTestCaseDesc NotifyWhenAvailable() to deal with global updates and be signalled
514 correctly when screen is unplugged.
516 @SYMTestPriority High
518 @SYMTestStatus Implemented
521 The test consists of a double-buffered surface, visible on screens A
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
529 5 Plug in screen A. (notification is still in a progress )
530 6 Make global submit update with notify when available for
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).
539 void CTSurfaceUpdateInteg::TestCase2L()
541 INFO_PRINTF1(_L("Exercising NotifyWhenAvailable while some screens are disconnected."));
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);
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
555 INFO_PRINTF1(_L("Fill the surface with the blue color"));
556 iSurfaceHelper->FillRectangleL(iSurfaceDoubleBuffered, TPoint(), windowSize, KRgbBlue);
558 INFO_PRINTF1(_L("Disconnect the screen while notify when available request is still in a progress"));
559 TRequestStatus status;
560 TSwitchDisplayAndReleaseBuffer param;
563 param.iSurfaceId=iSurfaceDoubleBuffered;
564 CCommandDispatcher commandDispatcher(CCommandDispatcher::EDisconnectDisplayAndReleaseBuffer, ¶m);
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);
579 INFO_PRINTF1(_L("Connect the screen while notify when available request is still in a progress"));
580 CCommandDispatcher commandDispatcher1(CCommandDispatcher::EConnectDisplayAndReleaseBuffer, ¶m);
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
586 TEST(res == KErrNone);
587 User::WaitForRequest(status);
588 TEST(status == KErrNone);
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);
596 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
597 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceDoubleBuffered, 0);
598 FillRefBitmap(KRgbGreen);
599 TEST(CompareAllScreens());
603 @SYMTestCaseID GRAPHIC-SURFACEUPDATE-0032
607 @SYMREQ REQ11599, REQ11600, REQ11601
609 @SYMTestCaseDesc NotifyWhenDisplayedXTimes() to deal with global
610 updates and be signalled correctly when screen is unplugged.
612 @SYMTestPriority High
614 @SYMTestStatus Implemented
617 The test consists of a single-buffered surface, S1, visible on
618 screens A (master) and B.
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
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
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
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
646 void CTSurfaceUpdateInteg::TestCase3()
648 INFO_PRINTF1(_L("Exercising NotifyWhenDisplayedXTimes while some screen is disconnected."));
650 TRequestStatus status;
651 TInt count = 100 * 2;
652 iSurfaceUpdate.NotifyWhenDisplayedXTimes(count, status);
653 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
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);
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);
670 iSurfaceUpdate.NotifyWhenDisplayedXTimes(count, status);
671 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
672 User::WaitForRequest(status);
673 TEST(status == KErrNone);
675 // Make sure other surface is not visible
676 iWindowAbove11->Window()->SetVisible(EFalse);
678 User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
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);
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);
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
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);
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
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);
725 iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurface, 0);
726 User::After(TTimeIntervalMicroSeconds32(100000)); //useful for visual checking
727 TEST(CompareAllScreens());
730 void CTSurfaceUpdateInteg::RunTestCaseL(TInt aCurTestCase)
732 ((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
738 if((static_cast <CTSurfaceUpdateIntegStep*> (iStep)) -> IsScreenCaptureSupported() && (iNumOfScreens > 1))
740 ((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(_L("GRAPHIC-SURFACEUPDATE-0026"));
741 INFO_PRINTF1(_L("TestCase1"));
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());
756 ((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(_L("GRAPHIC-SURFACEUPDATE-0031"));
757 INFO_PRINTF1(_L("TestCase2"));
763 ((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(_L("GRAPHIC-SURFACEUPDATE-0032"));
764 INFO_PRINTF1(_L("TestCase3"));
770 ((CTSurfaceUpdateIntegStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
771 ((CTSurfaceUpdateIntegStep*)iStep)->CloseTMSGraphicsStep();
775 ((CTSurfaceUpdateIntegStep*)iStep)->RecordTestResultL();
778 _LIT(KCommandDispatcher, "CommandDispatcher");
779 const TUint KDefaultHeapSize=0x10000;
782 * Launch the command thread.
784 TInt CCommandDispatcher::Start()
786 RThread commandThread;
787 TInt res = KErrGeneral;
788 TBuf<64> commandThreadName;
789 TBuf<64> commandThreaMask;
791 // Guarantee uniqueness of thread name by using timestamp
795 TRAP(res, tm.FormatL(timeStamp, _L("_%H%T%S%C")));
801 commandThreadName.Append(KCommandDispatcher);
802 commandThreadName.Append(timeStamp);
803 commandThreaMask = commandThreadName;
804 commandThreaMask.Insert(0, _L("*"));
805 TFindThread findThread(commandThreaMask);
807 // Need to check that the thread exists.
808 if (findThread.Next(name)!=KErrNone)
810 // Create the thread for the server.
811 res = commandThread.Create(commandThreadName,
812 CCommandDispatcher::ThreadFunction,
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.
823 TRequestStatus rendezvousStatus;
824 commandThread.SetPriority(EPriorityNormal);
825 commandThread.Rendezvous(rendezvousStatus);
826 commandThread.Resume();
829 commandThread.Close();
833 TInt CCommandDispatcher::ThreadFunction(TAny* aAny)
835 // get clean-up stack
836 CTrapCleanup* cleanup=CTrapCleanup::New();
837 CCommandDispatcher* commandDispatcher = (CCommandDispatcher*) aAny;
838 TRAPD(res, commandDispatcher->ExecuteCommandL());
844 * Run commands in a thread different to the thread where the instance
845 * of the class was initialized.
847 void CCommandDispatcher::ExecuteCommandL()
851 case EDisconnectDisplayAndReleaseBuffer:
853 RSurfaceUpdateSession surfaceUpdate;
854 User::LeaveIfError(surfaceUpdate.Connect());
855 CleanupClosePushL(surfaceUpdate);
856 TSwitchDisplayAndReleaseBuffer* param = static_cast<TSwitchDisplayAndReleaseBuffer*>(iParam);
859 User::Leave(KErrArgument);
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);
870 case EConnectDisplayAndReleaseBuffer:
872 RSurfaceUpdateSession surfaceUpdate;
873 User::LeaveIfError(surfaceUpdate.Connect());
874 CleanupClosePushL(surfaceUpdate);
875 TSwitchDisplayAndReleaseBuffer* param = static_cast<TSwitchDisplayAndReleaseBuffer*>(iParam);
878 User::Leave(KErrArgument);
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);
890 User::Leave(KErrNotSupported);
896 __CONSTRUCT_STEP__(SurfaceUpdateInteg)
899 * Retrieve screen capturing plug-in, if succeed set a flag.
901 void CTSurfaceUpdateIntegStep::TestSetupL()
903 // check if the screen capture plug-in presents in the system
905 User::LeaveIfError(ws.Connect());
906 CleanupClosePushL(ws);
908 TInt numOfScreens = ws.NumberOfScreens();
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);
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);
921 MTestScreenCapture* csc = static_cast<MTestScreenCapture*> (wsDev->GetInterface(MTestScreenCapture::KUidTestScreenCaptureIf));
924 INFO_PRINTF1(_L("Screen capture plug-in presents in the system."));
925 iScreenCapture = ETrue;
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"));
933 CleanupStack::PopAndDestroy(2, &ws); //ws, wsDev
936 void CTSurfaceUpdateIntegStep::TestClose()