Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/scheduler/scheduler.h" | 5 #include "cc/scheduler/scheduler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history = | 239 scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history = |
| 240 FakeCompositorTimingHistory::Create(); | 240 FakeCompositorTimingHistory::Create(); |
| 241 fake_compositor_timing_history_ = fake_compositor_timing_history.get(); | 241 fake_compositor_timing_history_ = fake_compositor_timing_history.get(); |
| 242 | 242 |
| 243 scheduler_ = TestScheduler::Create( | 243 scheduler_ = TestScheduler::Create( |
| 244 now_src_.get(), client_.get(), scheduler_settings_, 0, | 244 now_src_.get(), client_.get(), scheduler_settings_, 0, |
| 245 task_runner_.get(), fake_external_begin_frame_source_.get(), | 245 task_runner_.get(), fake_external_begin_frame_source_.get(), |
| 246 fake_compositor_timing_history.Pass()); | 246 fake_compositor_timing_history.Pass()); |
| 247 DCHECK(scheduler_); | 247 DCHECK(scheduler_); |
| 248 client_->set_scheduler(scheduler_.get()); | 248 client_->set_scheduler(scheduler_.get()); |
| 249 | |
| 250 // Use large estimates by default to avoid latency recovery | |
| 251 // in most tests. | |
| 252 base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); | |
| 253 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
| 254 one_second); | |
| 255 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
| 256 one_second); | |
| 257 fake_compositor_timing_history_->SetDrawDurationEstimate(one_second); | |
| 258 | |
| 249 return scheduler_.get(); | 259 return scheduler_.get(); |
| 250 } | 260 } |
| 251 | 261 |
| 252 void CreateSchedulerAndInitSurface() { | 262 void CreateSchedulerAndInitSurface() { |
| 253 CreateScheduler(); | 263 CreateScheduler(); |
| 254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); | 264 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit()); |
| 255 } | 265 } |
| 256 | 266 |
| 257 void SetUpScheduler(bool initSurface) { | 267 void SetUpScheduler(bool initSurface) { |
| 258 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface); | 268 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 BeginFrameArgs args = | 387 BeginFrameArgs args = |
| 378 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); | 388 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); |
| 379 fake_external_begin_frame_source_->TestOnBeginFrame(args); | 389 fake_external_begin_frame_source_->TestOnBeginFrame(args); |
| 380 return args; | 390 return args; |
| 381 } | 391 } |
| 382 | 392 |
| 383 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { | 393 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { |
| 384 return fake_external_begin_frame_source_.get(); | 394 return fake_external_begin_frame_source_.get(); |
| 385 } | 395 } |
| 386 | 396 |
| 387 void MainFrameInHighLatencyMode( | 397 void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame); |
| 388 int64 begin_main_frame_to_commit_estimate_in_ms, | 398 void ImplFrameSkippedAfterLateSwapAck(bool swap_ack_before_deadline); |
| 389 int64 commit_to_activate_estimate_in_ms, | 399 void ImplFrameIsNotSkippedAfterLateSwapAck(); |
| 390 bool impl_latency_takes_priority, | |
| 391 bool should_send_begin_main_frame); | |
| 392 void BeginFramesNotFromClient(bool use_external_begin_frame_source, | 400 void BeginFramesNotFromClient(bool use_external_begin_frame_source, |
| 393 bool throttle_frame_production); | 401 bool throttle_frame_production); |
| 394 void BeginFramesNotFromClient_SwapThrottled( | 402 void BeginFramesNotFromClient_SwapThrottled( |
| 395 bool use_external_begin_frame_source, | 403 bool use_external_begin_frame_source, |
| 396 bool throttle_frame_production); | 404 bool throttle_frame_production); |
| 397 | 405 |
| 398 scoped_ptr<base::SimpleTestTickClock> now_src_; | 406 scoped_ptr<base::SimpleTestTickClock> now_src_; |
| 399 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; | 407 scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
| 400 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; | 408 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_; |
| 401 SchedulerSettings scheduler_settings_; | 409 SchedulerSettings scheduler_settings_; |
| (...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1282 // Scheduler loses output surface, and stops waiting for ready to draw signal. | 1290 // Scheduler loses output surface, and stops waiting for ready to draw signal. |
| 1283 client_->Reset(); | 1291 client_->Reset(); |
| 1284 scheduler_->DidLoseOutputSurface(); | 1292 scheduler_->DidLoseOutputSurface(); |
| 1285 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | 1293 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); |
| 1286 task_runner().RunPendingTasks(); // Run posted deadline. | 1294 task_runner().RunPendingTasks(); // Run posted deadline. |
| 1287 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); | 1295 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); |
| 1288 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); | 1296 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); |
| 1289 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); | 1297 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); |
| 1290 } | 1298 } |
| 1291 | 1299 |
| 1292 void SchedulerTest::MainFrameInHighLatencyMode( | 1300 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit( |
| 1293 int64 begin_main_frame_to_commit_estimate_in_ms, | 1301 bool expect_send_begin_main_frame) { |
| 1294 int64 commit_to_activate_estimate_in_ms, | |
| 1295 bool impl_latency_takes_priority, | |
| 1296 bool should_send_begin_main_frame) { | |
| 1297 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1298 SetUpScheduler(true); | |
| 1299 | |
| 1300 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
| 1301 base::TimeDelta::FromMilliseconds( | |
| 1302 begin_main_frame_to_commit_estimate_in_ms)); | |
| 1303 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
| 1304 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms)); | |
| 1305 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
| 1306 base::TimeDelta::FromMilliseconds(1)); | |
| 1307 | |
| 1308 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority); | |
| 1309 | |
| 1310 // Impl thread hits deadline before commit finishes. | 1302 // Impl thread hits deadline before commit finishes. |
| 1311 scheduler_->SetNeedsCommit(); | 1303 scheduler_->SetNeedsCommit(); |
| 1312 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | 1304 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1313 EXPECT_SCOPED(AdvanceFrame()); | 1305 EXPECT_SCOPED(AdvanceFrame()); |
| 1314 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | 1306 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1315 task_runner().RunPendingTasks(); // Run posted deadline. | 1307 task_runner().RunPendingTasks(); // Run posted deadline. |
|
sunnyps
2015/07/08 22:37:13
nit: RunTasksWhile(DeadlinePending(true))
brianderson
2015/07/09 01:28:11
Done.
| |
| 1316 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1308 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1317 scheduler_->NotifyBeginMainFrameStarted(); | 1309 scheduler_->NotifyBeginMainFrameStarted(); |
| 1318 scheduler_->NotifyReadyToCommit(); | 1310 scheduler_->NotifyReadyToCommit(); |
| 1319 scheduler_->NotifyReadyToActivate(); | 1311 scheduler_->NotifyReadyToActivate(); |
|
sunnyps
2015/07/08 22:37:13
Can you add the necessary EXPECT_ACTION calls here
brianderson
2015/07/09 01:28:11
Done.
| |
| 1320 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1312 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1321 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | 1313 EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame")); |
| 1322 | 1314 |
| 1323 client_->Reset(); | 1315 client_->Reset(); |
| 1324 scheduler_->SetNeedsCommit(); | 1316 scheduler_->SetNeedsCommit(); |
| 1325 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1317 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1326 EXPECT_SCOPED(AdvanceFrame()); | 1318 EXPECT_SCOPED(AdvanceFrame()); |
| 1327 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | 1319 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); |
| 1328 task_runner().RunPendingTasks(); // Run posted deadline. | 1320 task_runner().RunPendingTasks(); // Run posted deadline. |
| 1329 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(), | 1321 EXPECT_EQ(expect_send_begin_main_frame, |
| 1330 should_send_begin_main_frame); | 1322 scheduler_->MainThreadIsInHighLatencyMode()); |
| 1331 EXPECT_EQ(client_->HasAction("ScheduledActionSendBeginMainFrame"), | 1323 EXPECT_EQ(expect_send_begin_main_frame, |
| 1332 should_send_begin_main_frame); | 1324 client_->HasAction("ScheduledActionSendBeginMainFrame")); |
| 1333 } | 1325 } |
| 1334 | 1326 |
| 1335 TEST_F(SchedulerTest, | 1327 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) { |
| 1336 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { | 1328 scheduler_settings_.use_external_begin_frame_source = true; |
| 1337 // Set up client so that estimates indicate that we can commit and activate | 1329 SetUpScheduler(true); |
| 1338 // before the deadline (~8ms by default). | 1330 |
| 1339 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); | 1331 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1340 } | 1332 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1341 | 1333 |
| 1342 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { | 1334 bool expect_send_begin_main_frame = false; |
| 1343 // Set up client so that estimates indicate that the commit cannot finish | 1335 EXPECT_SCOPED( |
| 1344 // before the deadline (~8ms by default). | 1336 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1345 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); | 1337 } |
| 1346 } | 1338 |
| 1347 | 1339 TEST_F(SchedulerTest, |
| 1348 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { | 1340 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) { |
|
sunnyps
2015/07/08 22:37:13
This test should be generalized - we want to check
brianderson
2015/07/09 01:28:11
Not sure if this needs to be generalized. See my c
| |
| 1349 // Set up client so that estimates indicate that the activate cannot finish | 1341 scheduler_settings_.use_external_begin_frame_source = true; |
| 1350 // before the deadline (~8ms by default). | 1342 SetUpScheduler(true); |
| 1351 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); | 1343 scheduler_->SetImplLatencyTakesPriority(true); |
| 1352 } | 1344 |
| 1353 | 1345 auto fast_duration = base::TimeDelta::FromMilliseconds(1); |
| 1354 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { | 1346 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); |
| 1355 // Set up client so that estimates indicate that we can commit and activate | 1347 |
| 1356 // before the deadline (~8ms by default), but also enable impl latency takes | 1348 bool expect_send_begin_main_frame = true; |
| 1357 // priority mode. | 1349 EXPECT_SCOPED( |
| 1358 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); | 1350 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); |
| 1351 } | |
| 1352 | |
| 1353 TEST_F(SchedulerTest, | |
| 1354 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) { | |
| 1355 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1356 SetUpScheduler(true); | |
| 1357 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1358 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1359 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1360 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
| 1361 slow_duration); | |
| 1362 | |
| 1363 bool expect_send_begin_main_frame = true; | |
| 1364 EXPECT_SCOPED( | |
| 1365 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); | |
| 1366 } | |
| 1367 | |
| 1368 TEST_F(SchedulerTest, | |
| 1369 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) { | |
| 1370 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1371 SetUpScheduler(true); | |
| 1372 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1373 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1374 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1375 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
| 1376 slow_duration); | |
| 1377 | |
| 1378 bool expect_send_begin_main_frame = true; | |
| 1379 EXPECT_SCOPED( | |
| 1380 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); | |
| 1381 } | |
| 1382 | |
| 1383 TEST_F(SchedulerTest, | |
| 1384 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) { | |
| 1385 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1386 SetUpScheduler(true); | |
| 1387 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1388 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1389 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1390 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration); | |
| 1391 | |
| 1392 bool expect_send_begin_main_frame = true; | |
| 1393 EXPECT_SCOPED( | |
| 1394 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); | |
| 1395 } | |
| 1396 | |
| 1397 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) { | |
| 1398 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1399 SetUpScheduler(true); | |
| 1400 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1401 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1402 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1403 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); | |
| 1404 | |
| 1405 bool expect_send_begin_main_frame = true; | |
| 1406 EXPECT_SCOPED( | |
| 1407 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame)); | |
| 1408 } | |
| 1409 | |
| 1410 void SchedulerTest::ImplFrameSkippedAfterLateSwapAck( | |
| 1411 bool swap_ack_before_deadline) { | |
| 1412 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1413 SetUpScheduler(true); | |
| 1414 | |
| 1415 // Use estimates that indicate commit and activate can finish before the | |
| 1416 // deadline. | |
|
sunnyps
2015/07/08 22:37:13
nit: Move setting the estimates to the test - so t
brianderson
2015/07/09 01:28:11
Done.
| |
| 1417 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1418 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1419 | |
| 1420 // To get into a high latency state, this test disables automatic swap acks. | |
| 1421 scheduler_->SetMaxSwapsPending(1); | |
| 1422 client_->SetAutomaticSwapAck(false); | |
| 1423 | |
| 1424 // Draw and swap for first BeginFrame | |
| 1425 client_->Reset(); | |
| 1426 scheduler_->SetNeedsCommit(); | |
| 1427 scheduler_->SetNeedsRedraw(); | |
| 1428 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1429 SendNextBeginFrame(); | |
| 1430 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4); | |
| 1431 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4); | |
| 1432 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
| 1433 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4); | |
| 1434 | |
| 1435 client_->Reset(); | |
| 1436 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1437 scheduler_->NotifyReadyToCommit(); | |
| 1438 scheduler_->NotifyReadyToActivate(); | |
| 1439 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1440 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1441 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
| 1442 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
| 1443 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
| 1444 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
| 1445 | |
| 1446 // Verify we skip every other frame if the swap ack consistently | |
| 1447 // comes back late. | |
| 1448 for (int i = 0; i < 10; i++) { | |
| 1449 // Not calling scheduler_->DidSwapBuffersComplete() until after next | |
| 1450 // BeginImplFrame puts the impl thread in high latency mode. | |
| 1451 client_->Reset(); | |
| 1452 scheduler_->SetNeedsCommit(); | |
| 1453 scheduler_->SetNeedsRedraw(); | |
| 1454 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1455 SendNextBeginFrame(); | |
| 1456 // Verify that we skip the BeginImplFrame | |
| 1457 EXPECT_NO_ACTION(client_); | |
| 1458 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
| 1459 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1460 | |
| 1461 // Verify that we do not perform any actions after we are no longer | |
| 1462 // swap throttled. | |
| 1463 client_->Reset(); | |
| 1464 if (swap_ack_before_deadline) { | |
| 1465 // It shouldn't matter if the swap ack comes back before the deadline... | |
| 1466 scheduler_->DidSwapBuffersComplete(); | |
| 1467 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1468 } else { | |
| 1469 // ... or after the deadline. | |
| 1470 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1471 scheduler_->DidSwapBuffersComplete(); | |
| 1472 } | |
| 1473 EXPECT_NO_ACTION(client_); | |
| 1474 | |
| 1475 // Verify that we start the next BeginImplFrame and continue normally | |
| 1476 // after having just skipped a BeginImplFrame. | |
| 1477 client_->Reset(); | |
| 1478 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1479 scheduler_->SetNeedsCommit(); | |
|
sunnyps
2015/07/08 22:37:13
Shouldn't need to call SetNeedsCommit or SetNeedsR
brianderson
2015/07/09 01:28:12
Ah, these calls are redundant. Will remove them.
| |
| 1480 scheduler_->SetNeedsRedraw(); | |
| 1481 SendNextBeginFrame(); | |
| 1482 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); | |
| 1483 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); | |
| 1484 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); | |
| 1485 | |
| 1486 client_->Reset(); | |
| 1487 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1488 scheduler_->NotifyReadyToCommit(); | |
| 1489 scheduler_->NotifyReadyToActivate(); | |
| 1490 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1491 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
| 1492 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
| 1493 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
| 1494 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
| 1495 } | |
| 1496 } | |
| 1497 | |
| 1498 TEST_F(SchedulerTest, ImplFrameSkippedAfterLateSwapAck_SwapAckThenDeadline) { | |
| 1499 bool swap_ack_before_deadline = true; | |
| 1500 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline)); | |
| 1501 } | |
| 1502 | |
| 1503 TEST_F(SchedulerTest, ImplFrameSkippedAfterLateSwapAck_DeadlineThenSwapAck) { | |
| 1504 bool swap_ack_before_deadline = false; | |
| 1505 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline)); | |
| 1506 } | |
| 1507 | |
| 1508 void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() { | |
| 1509 // To get into a high latency state, this test disables automatic swap acks. | |
| 1510 scheduler_->SetMaxSwapsPending(1); | |
| 1511 client_->SetAutomaticSwapAck(false); | |
| 1512 | |
| 1513 // Draw and swap for first BeginFrame | |
| 1514 client_->Reset(); | |
| 1515 scheduler_->SetNeedsCommit(); | |
| 1516 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1517 SendNextBeginFrame(); | |
| 1518 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); | |
| 1519 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); | |
| 1520 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); | |
| 1521 | |
| 1522 client_->Reset(); | |
| 1523 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1524 scheduler_->NotifyReadyToCommit(); | |
| 1525 scheduler_->NotifyReadyToActivate(); | |
| 1526 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1527 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1528 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
| 1529 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
| 1530 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
| 1531 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
| 1532 | |
| 1533 // Verify impl thread consistently operates in high latency mode | |
| 1534 // without skipping any frames. | |
| 1535 for (int i = 0; i < 10; i++) { | |
| 1536 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame | |
| 1537 // puts the impl thread in high latency mode. | |
| 1538 client_->Reset(); | |
| 1539 scheduler_->SetNeedsCommit(); | |
| 1540 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1541 SendNextBeginFrame(); | |
| 1542 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
| 1543 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
| 1544 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1545 | |
| 1546 client_->Reset(); | |
| 1547 scheduler_->DidSwapBuffersComplete(); | |
| 1548 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1549 scheduler_->NotifyReadyToCommit(); | |
| 1550 scheduler_->NotifyReadyToActivate(); | |
| 1551 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1552 | |
| 1553 // Verify that we don't skip the actions of the BeginImplFrame | |
| 1554 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5); | |
| 1555 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5); | |
| 1556 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5); | |
| 1557 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); | |
| 1558 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); | |
| 1559 } | |
| 1560 } | |
| 1561 | |
| 1562 TEST_F(SchedulerTest, | |
| 1563 ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) { | |
| 1564 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1565 SetUpScheduler(true); | |
| 1566 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1567 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1568 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1569 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
| 1570 slow_duration); | |
| 1571 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); | |
| 1572 } | |
| 1573 | |
| 1574 TEST_F(SchedulerTest, | |
| 1575 ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) { | |
| 1576 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1577 SetUpScheduler(true); | |
| 1578 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1579 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1580 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1581 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
| 1582 slow_duration); | |
| 1583 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); | |
| 1584 } | |
| 1585 | |
| 1586 TEST_F(SchedulerTest, | |
| 1587 ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) { | |
| 1588 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1589 SetUpScheduler(true); | |
| 1590 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1591 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1592 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1593 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration); | |
| 1594 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); | |
| 1595 } | |
| 1596 | |
| 1597 TEST_F(SchedulerTest, | |
| 1598 ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) { | |
| 1599 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1600 SetUpScheduler(true); | |
| 1601 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1602 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1603 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1604 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); | |
| 1605 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); | |
| 1606 } | |
| 1607 | |
| 1608 TEST_F(SchedulerTest, | |
| 1609 MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck) { | |
| 1610 // Set up client with custom estimates. | |
| 1611 // This test starts off with expensive estimates to prevent latency recovery | |
| 1612 // initially, then lowers the estimates to enable it once both the main | |
| 1613 // and impl threads are in a high latency mode. | |
| 1614 scheduler_settings_.use_external_begin_frame_source = true; | |
| 1615 SetUpScheduler(true); | |
| 1616 | |
| 1617 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
| 1618 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1619 auto slow_duration = base::TimeDelta::FromSeconds(1); | |
| 1620 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); | |
|
sunnyps
2015/07/08 22:37:13
This doesn't match the comment above.
brianderson
2015/07/09 01:28:12
Done.
| |
| 1621 | |
| 1622 // To get into a high latency state, this test disables automatic swap acks. | |
| 1623 scheduler_->SetMaxSwapsPending(1); | |
| 1624 client_->SetAutomaticSwapAck(false); | |
| 1625 | |
| 1626 // Impl thread hits deadline before commit finishes to make | |
| 1627 // MainThreadIsInHighLatencyMode true | |
| 1628 client_->Reset(); | |
| 1629 scheduler_->SetNeedsCommit(); | |
| 1630 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1631 EXPECT_SCOPED(AdvanceFrame()); | |
| 1632 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1633 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1634 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1635 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1636 scheduler_->NotifyReadyToCommit(); | |
| 1637 scheduler_->NotifyReadyToActivate(); | |
| 1638 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1639 | |
| 1640 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); | |
| 1641 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); | |
| 1642 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); | |
| 1643 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); | |
| 1644 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); | |
| 1645 | |
| 1646 // Draw and swap for first commit, start second commit. | |
| 1647 client_->Reset(); | |
| 1648 scheduler_->SetNeedsCommit(); | |
| 1649 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1650 EXPECT_SCOPED(AdvanceFrame()); | |
| 1651 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1652 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1653 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1654 scheduler_->NotifyReadyToCommit(); | |
| 1655 scheduler_->NotifyReadyToActivate(); | |
| 1656 | |
| 1657 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); | |
| 1658 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6); | |
| 1659 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); | |
| 1660 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); | |
| 1661 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6); | |
| 1662 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6); | |
| 1663 | |
| 1664 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame | |
| 1665 // to put the impl thread in a high latency mode. | |
| 1666 client_->Reset(); | |
| 1667 scheduler_->SetNeedsCommit(); | |
| 1668 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1669 EXPECT_SCOPED(AdvanceFrame()); | |
| 1670 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1671 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1672 scheduler_->DidSwapBuffersComplete(); | |
| 1673 | |
| 1674 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
| 1675 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
| 1676 // Note: BeginMainFrame and swap are skipped here because of | |
| 1677 // swap ack backpressure, not because of latency recovery. | |
| 1678 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | |
| 1679 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
|
sunnyps
2015/07/08 22:37:13
EXPECT_TRUE that both impl thread and main thread
brianderson
2015/07/09 01:28:12
Done.
| |
| 1680 | |
| 1681 // Lower estimates so that the scheduler will attempt latency recovery. | |
| 1682 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
| 1683 | |
| 1684 // Now that both threads are in a high latency mode, make sure we | |
| 1685 // skip the BeginMainFrame, then the BeginImplFrame, but not both | |
| 1686 // at the same time. | |
| 1687 | |
| 1688 // Verify we skip BeginMainFrame first. | |
| 1689 client_->Reset(); | |
| 1690 // Previous commit request is still outstanding. | |
| 1691 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
| 1692 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1693 SendNextBeginFrame(); | |
|
sunnyps
2015/07/08 22:37:13
Same as above (before the deadline runs).
brianderson
2015/07/09 01:28:12
Thanks for the suggestion. Found out I was calling
| |
| 1694 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1695 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
|
sunnyps
2015/07/08 22:37:13
nit: Move this EXPECT below so that it reads seque
brianderson
2015/07/09 01:28:11
Done.
| |
| 1696 | |
| 1697 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); | |
| 1698 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); | |
| 1699 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); | |
| 1700 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | |
|
sunnyps
2015/07/08 22:37:13
nit: Don't need the last EXPECT_FALSE.
brianderson
2015/07/09 01:28:11
Done.
| |
| 1701 | |
| 1702 // Verify we skip the BeginImplFrame second. | |
| 1703 client_->Reset(); | |
| 1704 // Previous commit request is still outstanding. | |
| 1705 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
| 1706 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1707 SendNextBeginFrame(); | |
| 1708 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1709 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1710 scheduler_->DidSwapBuffersComplete(); | |
| 1711 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1712 | |
| 1713 EXPECT_NO_ACTION(client_); | |
| 1714 | |
| 1715 // Then verify we operate in a low latency mode. | |
| 1716 client_->Reset(); | |
| 1717 // Previous commit request is still outstanding. | |
| 1718 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
| 1719 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1720 SendNextBeginFrame(); | |
| 1721 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1722 scheduler_->NotifyBeginMainFrameStarted(); | |
| 1723 scheduler_->NotifyReadyToCommit(); | |
| 1724 scheduler_->NotifyReadyToActivate(); | |
| 1725 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
| 1726 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1727 scheduler_->DidSwapBuffersComplete(); | |
| 1728 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
| 1729 | |
| 1730 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); | |
| 1731 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6); | |
| 1732 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6); | |
| 1733 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6); | |
| 1734 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6); | |
| 1735 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6); | |
| 1359 } | 1736 } |
| 1360 | 1737 |
| 1361 TEST_F( | 1738 TEST_F( |
| 1362 SchedulerTest, | 1739 SchedulerTest, |
| 1363 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { | 1740 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { |
| 1364 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main | 1741 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main |
| 1365 // thread. This prevents the scheduler from receiving any pending swap acks. | 1742 // thread. This prevents the scheduler from receiving any pending swap acks. |
| 1366 | 1743 |
| 1367 // Since we are simulating a long commit, set up a client with draw duration | 1744 // Since we are simulating a long commit, set up a client with draw duration |
| 1368 // estimates that prevent skipping main frames to get to low latency mode. | 1745 // estimates that prevent skipping main frames to get to low latency mode. |
| (...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2955 scheduler_->SetImplLatencyTakesPriority(true); | 3332 scheduler_->SetImplLatencyTakesPriority(true); |
| 2956 scheduler_->SetChildrenNeedBeginFrames(true); | 3333 scheduler_->SetChildrenNeedBeginFrames(true); |
| 2957 | 3334 |
| 2958 EXPECT_SCOPED(AdvanceFrame()); | 3335 EXPECT_SCOPED(AdvanceFrame()); |
| 2959 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); | 3336 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); |
| 2960 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); | 3337 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); |
| 2961 } | 3338 } |
| 2962 | 3339 |
| 2963 } // namespace | 3340 } // namespace |
| 2964 } // namespace cc | 3341 } // namespace cc |
| OLD | NEW |