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 MainFrameInHighLatencyMode(bool should_send_begin_main_frame); |
388 int64 begin_main_frame_to_commit_estimate_in_ms, | 398 void ImplFrameInHighLatencySkipImplFrame(bool swap_ack_before_deadline); |
389 int64 commit_to_activate_estimate_in_ms, | 399 void ImplFrameInHighLatencyDontSkipImplFrame(); |
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::MainFrameInHighLatencyMode( |
mithro-old
2015/07/08 00:54:51
nit: I think this could be named better.
My thoug
| |
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. |
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(); |
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")); |
1325 } | |
1326 | |
1327 TEST_F(SchedulerTest, SkipMainFrameIfHighLatencyAndCanDrawBeforeDeadline) { | |
mithro-old
2015/07/08 00:54:51
nit: s/IfHighLatency/IfLateCommit/ or maybe IfMiss
| |
1328 scheduler_settings_.use_external_begin_frame_source = true; | |
1329 SetUpScheduler(true); | |
1330 | |
1331 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
1332 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
1333 | |
1334 bool expect_send_begin_main_frame = false; | |
1335 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame)); | |
1336 } | |
1337 | |
1338 TEST_F(SchedulerTest, DontSkipMainFrameInPreferImplLatencyMode) { | |
1339 scheduler_settings_.use_external_begin_frame_source = true; | |
1340 SetUpScheduler(true); | |
1341 scheduler_->SetImplLatencyTakesPriority(true); | |
1342 | |
1343 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
1344 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
1345 | |
1346 bool expect_send_begin_main_frame = true; | |
1347 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame)); | |
1348 } | |
1349 | |
1350 TEST_F(SchedulerTest, DontSkipMainFrameIfCommitEstimateTooLong) { | |
1351 scheduler_settings_.use_external_begin_frame_source = true; | |
1352 SetUpScheduler(true); | |
1353 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
mithro-old
2015/07/08 00:54:51
nit: It seems like it could be dangerous to be usi
| |
1354 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1355 base::TimeDelta::FromMilliseconds(16)); | |
mithro-old
2015/07/08 00:54:51
nit: Should we use a larger value here?
| |
1356 bool expect_send_begin_main_frame = true; | |
1357 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame)); | |
1358 } | |
1359 | |
1360 TEST_F(SchedulerTest, DontSkipMainFrameIfReadyToActivateEstimateTooLong) { | |
1361 scheduler_settings_.use_external_begin_frame_source = true; | |
1362 SetUpScheduler(true); | |
1363 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1364 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1365 base::TimeDelta::FromMilliseconds(16)); | |
1366 bool expect_send_begin_main_frame = true; | |
1367 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame)); | |
1368 } | |
1369 | |
1370 TEST_F(SchedulerTest, DontSkipMainFrameIfActivateEstimateTooLong) { | |
1371 scheduler_settings_.use_external_begin_frame_source = true; | |
1372 SetUpScheduler(true); | |
1373 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1374 fake_compositor_timing_history_->SetActivateDurationEstimate( | |
1375 base::TimeDelta::FromMilliseconds(16)); | |
1376 bool expect_send_begin_main_frame = true; | |
1377 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame)); | |
1378 } | |
1379 | |
1380 TEST_F(SchedulerTest, DontSkipMainFrameIfDrawEstimateTooLong) { | |
1381 scheduler_settings_.use_external_begin_frame_source = true; | |
1382 SetUpScheduler(true); | |
1383 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1384 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
1385 base::TimeDelta::FromMilliseconds(16)); | |
1386 bool expect_send_begin_main_frame = true; | |
1387 EXPECT_SCOPED(MainFrameInHighLatencyMode(expect_send_begin_main_frame)); | |
1388 } | |
1389 | |
1390 void SchedulerTest::ImplFrameInHighLatencySkipImplFrame( | |
mithro-old
2015/07/08 00:54:51
nit: Name - see comments above too.
| |
1391 bool swap_ack_before_deadline) { | |
1392 // Set up client with specified estimates. | |
1393 scheduler_settings_.use_external_begin_frame_source = true; | |
1394 SetUpScheduler(true); | |
1395 | |
1396 // Use estimates that indicate commit and activate can finish before the | |
1397 // deadline. | |
1398 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
1399 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
1400 | |
1401 // To get into a high latency state, this test disables automatic swap acks. | |
1402 scheduler_->SetMaxSwapsPending(1); | |
1403 client_->SetAutomaticSwapAck(false); | |
1404 | |
1405 // Draw and swap for first BeginFrame | |
1406 client_->Reset(); | |
1407 scheduler_->SetNeedsCommit(); | |
1408 scheduler_->SetNeedsRedraw(); | |
1409 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1410 SendNextBeginFrame(); | |
1411 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4); | |
1412 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4); | |
1413 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1414 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4); | |
1415 | |
1416 client_->Reset(); | |
1417 scheduler_->NotifyBeginMainFrameStarted(); | |
1418 scheduler_->NotifyReadyToCommit(); | |
1419 scheduler_->NotifyReadyToActivate(); | |
1420 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1421 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1422 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
1423 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
1424 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1425 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
1426 | |
1427 // Verify we skip every other frame if the swap ack consistently | |
1428 // comes back late. | |
1429 for (int i = 0; i < 10; i++) { | |
1430 // Not calling scheduler_->DidSwapBuffersComplete() until after next | |
1431 // BeginImplFrame puts the impl thread in high latency mode. | |
1432 client_->Reset(); | |
1433 scheduler_->SetNeedsCommit(); | |
1434 scheduler_->SetNeedsRedraw(); | |
1435 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1436 SendNextBeginFrame(); | |
1437 // Verify that we skip the BeginImplFrame | |
1438 EXPECT_NO_ACTION(client_); | |
1439 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); | |
1440 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1441 | |
1442 // Verify that we do not perform any actions after we are no longer | |
1443 // swap throttled. | |
1444 // Also verify the scheduler logic that determines if we are in a high | |
mithro-old
2015/07/08 00:54:51
Where is the verification that this comment is ref
| |
1445 // latency mode is immune to whether or not the swap ack comes back before | |
1446 // or after the deadline. | |
1447 client_->Reset(); | |
1448 if (swap_ack_before_deadline) { | |
1449 scheduler_->DidSwapBuffersComplete(); | |
1450 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1451 } else { | |
1452 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1453 scheduler_->DidSwapBuffersComplete(); | |
1454 } | |
1455 EXPECT_NO_ACTION(client_); | |
1456 | |
1457 // Verify that we start the next BeginImplFrame and continue normally | |
1458 // after having just skipped a BeginImplFrame. | |
1459 client_->Reset(); | |
1460 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1461 scheduler_->SetNeedsCommit(); | |
1462 scheduler_->SetNeedsRedraw(); | |
1463 SendNextBeginFrame(); | |
1464 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); | |
1465 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); | |
1466 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); | |
1467 | |
1468 client_->Reset(); | |
1469 scheduler_->NotifyBeginMainFrameStarted(); | |
1470 scheduler_->NotifyReadyToCommit(); | |
1471 scheduler_->NotifyReadyToActivate(); | |
1472 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1473 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
1474 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
1475 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1476 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
1477 } | |
1333 } | 1478 } |
1334 | 1479 |
1335 TEST_F(SchedulerTest, | 1480 TEST_F(SchedulerTest, |
1336 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) { | 1481 SkipSwapIfHighLatencyAndCanDrawBeforeDeadline_SwapAckThenDeadline) { |
1337 // Set up client so that estimates indicate that we can commit and activate | 1482 bool swap_ack_before_deadline = true; |
1338 // before the deadline (~8ms by default). | 1483 EXPECT_SCOPED(ImplFrameInHighLatencySkipImplFrame(swap_ack_before_deadline)); |
1339 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false)); | 1484 } |
1340 } | 1485 |
1341 | 1486 TEST_F(SchedulerTest, |
1342 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) { | 1487 SkipSwapIfHighLatencyAndCanDrawBeforeDeadline_DeadlineThenSwapAck) { |
1343 // Set up client so that estimates indicate that the commit cannot finish | 1488 bool swap_ack_before_deadline = false; |
1344 // before the deadline (~8ms by default). | 1489 EXPECT_SCOPED(ImplFrameInHighLatencySkipImplFrame(swap_ack_before_deadline)); |
1345 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true)); | 1490 } |
1346 } | 1491 |
1347 | 1492 void SchedulerTest::ImplFrameInHighLatencyDontSkipImplFrame() { |
1348 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) { | 1493 // To get into a high latency state, this test disables automatic swap acks. |
1349 // Set up client so that estimates indicate that the activate cannot finish | 1494 scheduler_->SetMaxSwapsPending(1); |
1350 // before the deadline (~8ms by default). | 1495 client_->SetAutomaticSwapAck(false); |
1351 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); | 1496 |
1352 } | 1497 // Draw and swap for first BeginFrame |
1353 | 1498 client_->Reset(); |
1354 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { | 1499 scheduler_->SetNeedsCommit(); |
1355 // Set up client so that estimates indicate that we can commit and activate | 1500 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); |
1356 // before the deadline (~8ms by default), but also enable impl latency takes | 1501 SendNextBeginFrame(); |
1357 // priority mode. | 1502 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); |
1358 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); | 1503 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); |
1504 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); | |
1505 | |
1506 client_->Reset(); | |
1507 scheduler_->NotifyBeginMainFrameStarted(); | |
1508 scheduler_->NotifyReadyToCommit(); | |
1509 scheduler_->NotifyReadyToActivate(); | |
1510 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1511 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1512 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4); | |
1513 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4); | |
1514 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4); | |
1515 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4); | |
1516 | |
1517 // Verify impl thread consistently operates in high latency mode | |
1518 // without skipping any frames. | |
1519 for (int i = 0; i < 10; i++) { | |
1520 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame | |
1521 // puts the impl thread in high latency mode. | |
1522 client_->Reset(); | |
1523 scheduler_->SetNeedsCommit(); | |
1524 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1525 SendNextBeginFrame(); | |
1526 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); | |
1527 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); | |
1528 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1529 | |
1530 client_->Reset(); | |
1531 scheduler_->DidSwapBuffersComplete(); | |
1532 scheduler_->NotifyBeginMainFrameStarted(); | |
1533 scheduler_->NotifyReadyToCommit(); | |
1534 scheduler_->NotifyReadyToActivate(); | |
1535 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1536 | |
1537 // Verify that we don't skip the actions of the BeginImplFrame | |
1538 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5); | |
1539 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5); | |
1540 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5); | |
1541 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5); | |
1542 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5); | |
1543 } | |
1544 } | |
1545 | |
1546 TEST_F(SchedulerTest, DontSkipImplFrameIfCommitEstimateTooLong) { | |
1547 scheduler_settings_.use_external_begin_frame_source = true; | |
1548 SetUpScheduler(true); | |
1549 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1550 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate( | |
1551 base::TimeDelta::FromMilliseconds(16)); | |
1552 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame()); | |
1553 } | |
1554 | |
1555 TEST_F(SchedulerTest, DontSkipImplFrameIfReadyToActivateEstimateTooLong) { | |
1556 scheduler_settings_.use_external_begin_frame_source = true; | |
1557 SetUpScheduler(true); | |
1558 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1559 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( | |
1560 base::TimeDelta::FromMilliseconds(16)); | |
1561 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame()); | |
1562 } | |
1563 | |
1564 TEST_F(SchedulerTest, DontSkipImplFrameIfActivateEstimateTooLong) { | |
1565 scheduler_settings_.use_external_begin_frame_source = true; | |
1566 SetUpScheduler(true); | |
1567 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1568 fake_compositor_timing_history_->SetActivateDurationEstimate( | |
1569 base::TimeDelta::FromMilliseconds(16)); | |
1570 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame()); | |
1571 } | |
1572 | |
1573 TEST_F(SchedulerTest, DontSkipImplFrameIfDrawEstimateTooLong) { | |
1574 scheduler_settings_.use_external_begin_frame_source = true; | |
1575 SetUpScheduler(true); | |
1576 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1577 fake_compositor_timing_history_->SetDrawDurationEstimate( | |
1578 base::TimeDelta::FromMilliseconds(16)); | |
1579 EXPECT_SCOPED(ImplFrameInHighLatencyDontSkipImplFrame()); | |
1580 } | |
1581 | |
1582 TEST_F(SchedulerTest, MainAndSwapInHighLatencyMode) { | |
1583 // Set up client with custom estimates. | |
1584 // This test starts off with expensive estimates to prevent latency recovery | |
1585 // initially, then lowers the estimates to enable it once both the main | |
1586 // and impl threads are in a high latency mode. | |
1587 scheduler_settings_.use_external_begin_frame_source = true; | |
1588 SetUpScheduler(true); | |
1589 | |
1590 auto slow_duration = base::TimeDelta::FromMilliseconds(16); | |
1591 fake_compositor_timing_history_->SetAllEstimatesTo(base::TimeDelta()); | |
1592 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration); | |
1593 | |
1594 // To get into a high latency state, this test disables automatic swap acks. | |
1595 scheduler_->SetMaxSwapsPending(1); | |
1596 client_->SetAutomaticSwapAck(false); | |
1597 | |
1598 // Impl thread hits deadline before commit finishes to make | |
1599 // MainThreadIsInHighLatencyMode true | |
1600 client_->Reset(); | |
1601 scheduler_->SetNeedsCommit(); | |
1602 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1603 EXPECT_SCOPED(AdvanceFrame()); | |
1604 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1605 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1606 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1607 scheduler_->NotifyBeginMainFrameStarted(); | |
1608 scheduler_->NotifyReadyToCommit(); | |
1609 scheduler_->NotifyReadyToActivate(); | |
1610 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1611 | |
1612 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); | |
1613 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); | |
1614 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); | |
1615 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); | |
1616 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5); | |
1617 | |
1618 // Draw and swap for first commit, start second commit. | |
1619 client_->Reset(); | |
1620 scheduler_->SetNeedsCommit(); | |
1621 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1622 EXPECT_SCOPED(AdvanceFrame()); | |
1623 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1624 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1625 scheduler_->NotifyBeginMainFrameStarted(); | |
1626 scheduler_->NotifyReadyToCommit(); | |
1627 scheduler_->NotifyReadyToActivate(); | |
1628 | |
1629 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); | |
1630 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6); | |
1631 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); | |
1632 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); | |
1633 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6); | |
1634 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6); | |
1635 | |
1636 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame | |
1637 // to put the impl thread in a high latency mode. | |
1638 client_->Reset(); | |
1639 scheduler_->SetNeedsCommit(); | |
1640 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1641 EXPECT_SCOPED(AdvanceFrame()); | |
1642 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1643 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1644 scheduler_->DidSwapBuffersComplete(); | |
1645 | |
1646 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); | |
1647 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); | |
1648 // Note: BeginMainFrame and swap are skipped here because of | |
1649 // swap ack backpressure, not because of latency recovery. | |
1650 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | |
1651 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); | |
1652 | |
1653 // Lower estimates so that the scheduler will attempt latency recovery. | |
1654 auto fast_duration = base::TimeDelta::FromMilliseconds(1); | |
1655 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration); | |
1656 | |
1657 // Now that both threads are in a high latency mode, make sure we | |
1658 // skip the BeginMainFrame, then the BeginImplFrame, but not both | |
1659 // at the same time. | |
1660 | |
1661 // Verify we skip BeginMainFrame first. | |
1662 client_->Reset(); | |
1663 // Previous commit request is still outstanding. | |
1664 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
1665 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1666 SendNextBeginFrame(); | |
1667 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1668 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1669 | |
1670 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); | |
1671 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3); | |
1672 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); | |
1673 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame")); | |
1674 | |
1675 // Verify we skip the BeginImplFrame second. | |
1676 client_->Reset(); | |
1677 // Previous commit request is still outstanding. | |
1678 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
1679 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1680 SendNextBeginFrame(); | |
1681 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1682 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1683 scheduler_->DidSwapBuffersComplete(); | |
1684 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1685 | |
1686 EXPECT_NO_ACTION(client_); | |
1687 | |
1688 // Then verify we operate in a low latency mode. | |
1689 client_->Reset(); | |
1690 // Previous commit request is still outstanding. | |
1691 EXPECT_TRUE(scheduler_->NeedsCommit()); | |
1692 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1693 SendNextBeginFrame(); | |
1694 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1695 scheduler_->NotifyBeginMainFrameStarted(); | |
1696 scheduler_->NotifyReadyToCommit(); | |
1697 scheduler_->NotifyReadyToActivate(); | |
1698 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); | |
1699 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1700 scheduler_->DidSwapBuffersComplete(); | |
1701 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode()); | |
1702 | |
1703 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6); | |
1704 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6); | |
1705 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6); | |
1706 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6); | |
1707 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6); | |
1708 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6); | |
1359 } | 1709 } |
1360 | 1710 |
1361 TEST_F( | 1711 TEST_F( |
1362 SchedulerTest, | 1712 SchedulerTest, |
1363 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { | 1713 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) { |
1364 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main | 1714 // 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. | 1715 // thread. This prevents the scheduler from receiving any pending swap acks. |
1366 | 1716 |
1367 // Since we are simulating a long commit, set up a client with draw duration | 1717 // 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. | 1718 // 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); | 3305 scheduler_->SetImplLatencyTakesPriority(true); |
2956 scheduler_->SetChildrenNeedBeginFrames(true); | 3306 scheduler_->SetChildrenNeedBeginFrames(true); |
2957 | 3307 |
2958 EXPECT_SCOPED(AdvanceFrame()); | 3308 EXPECT_SCOPED(AdvanceFrame()); |
2959 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); | 3309 EXPECT_TRUE(client_->begin_frame_is_sent_to_children()); |
2960 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); | 3310 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path); |
2961 } | 3311 } |
2962 | 3312 |
2963 } // namespace | 3313 } // namespace |
2964 } // namespace cc | 3314 } // namespace cc |
OLD | NEW |