1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028 |
- // Copyright 2011 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "cc/scheduler/scheduler_state_machine.h"
- #include <stddef.h>
- #include "base/test/gtest_util.h"
- #include "base/trace_event/trace_event.h"
- #include "cc/scheduler/scheduler.h"
- #include "components/viz/common/frame_sinks/begin_frame_args.h"
- #include "components/viz/test/begin_frame_args_test.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- // Macro to compare two enum values and get nice output.
- // Without:
- // Value of: actual() Actual: 7
- // Expected: expected() Which is: 0
- // With:
- // Value of: actual() Actual: "ACTION_DRAW"
- // Expected: expected() Which is: "ACTION_NONE"
- #define EXPECT_ENUM_EQ(enum_tostring, expected, actual) \
- EXPECT_THAT(enum_tostring(actual), testing::Eq(enum_tostring(expected)))
- #define EXPECT_IMPL_FRAME_STATE(expected) \
- EXPECT_ENUM_EQ(BeginImplFrameStateToString, expected, \
- state.begin_impl_frame_state())
- #define EXPECT_MAIN_FRAME_STATE(expected) \
- EXPECT_ENUM_EQ(BeginMainFrameStateToString, expected, \
- state.BeginMainFrameState())
- #define EXPECT_ACTION(expected) \
- EXPECT_ENUM_EQ(ActionToString, expected, state.NextAction())
- #define EXPECT_ACTION_UPDATE_STATE(action) \
- EXPECT_ACTION(action); \
- if (action == SchedulerStateMachine::Action::DRAW_IF_POSSIBLE || \
- action == SchedulerStateMachine::Action::DRAW_FORCED) { \
- EXPECT_IMPL_FRAME_STATE( \
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE); \
- } \
- PerformAction(&state, action); \
- if (action == SchedulerStateMachine::Action::NONE) { \
- if (state.begin_impl_frame_state() == \
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE) \
- state.OnBeginImplFrameIdle(); \
- }
- #define SET_UP_STATE(state) \
- state.SetVisible(true); \
- EXPECT_ACTION_UPDATE_STATE( \
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION); \
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE); \
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit(); \
- state.SetCanDraw(true)
- namespace cc {
- namespace {
- const char* BeginImplFrameStateToString(
- SchedulerStateMachine::BeginImplFrameState state) {
- using BeginImplFrameState = SchedulerStateMachine::BeginImplFrameState;
- switch (state) {
- case BeginImplFrameState::IDLE:
- return "BeginImplFrameState::IDLE";
- case BeginImplFrameState::INSIDE_BEGIN_FRAME:
- return "BeginImplFrameState::INSIDE_BEGIN_FRAME";
- case BeginImplFrameState::INSIDE_DEADLINE:
- return "BeginImplFrameState::INSIDE_DEADLINE";
- }
- NOTREACHED();
- return "???";
- }
- const char* BeginMainFrameStateToString(
- SchedulerStateMachine::BeginMainFrameState state) {
- using BeginMainFrameState = SchedulerStateMachine::BeginMainFrameState;
- switch (state) {
- case BeginMainFrameState::IDLE:
- return "BeginMainFrameState::IDLE";
- case BeginMainFrameState::SENT:
- return "BeginMainFrameState::SENT";
- case BeginMainFrameState::READY_TO_COMMIT:
- return "BeginMainFrameState::READY_TO_COMMIT";
- }
- NOTREACHED();
- return "???";
- }
- const char* ActionToString(SchedulerStateMachine::Action action) {
- using Action = SchedulerStateMachine::Action;
- switch (action) {
- case Action::NONE:
- return "Action::NONE";
- case Action::SEND_BEGIN_MAIN_FRAME:
- return "Action::SEND_BEGIN_MAIN_FRAME";
- case Action::COMMIT:
- return "Action::COMMIT";
- case Action::POST_COMMIT:
- return "Action::POST_COMMIT";
- case Action::ACTIVATE_SYNC_TREE:
- return "Action::ACTIVATE_SYNC_TREE";
- case Action::DRAW_IF_POSSIBLE:
- return "Action::DRAW_IF_POSSIBLE";
- case Action::DRAW_FORCED:
- return "Action::DRAW_FORCED";
- case Action::DRAW_ABORT:
- return "Action::DRAW_ABORT";
- case Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION:
- return "Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION";
- case Action::PREPARE_TILES:
- return "Action::PREPARE_TILES";
- case Action::INVALIDATE_LAYER_TREE_FRAME_SINK:
- return "Action::INVALIDATE_LAYER_TREE_FRAME_SINK";
- case Action::PERFORM_IMPL_SIDE_INVALIDATION:
- return "Action::PERFORM_IMPL_SIDE_INVALIDATION";
- case Action::NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL:
- return "Action::NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL";
- case Action::NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON:
- return "Action::NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON";
- }
- NOTREACHED();
- return "???";
- }
- const bool kAnimateOnly = false;
- const SchedulerStateMachine::BeginImplFrameState all_begin_impl_frame_states[] =
- {
- SchedulerStateMachine::BeginImplFrameState::IDLE,
- SchedulerStateMachine::BeginImplFrameState::INSIDE_BEGIN_FRAME,
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE,
- };
- const SchedulerStateMachine::BeginMainFrameState begin_main_frame_states[] = {
- SchedulerStateMachine::BeginMainFrameState::IDLE,
- SchedulerStateMachine::BeginMainFrameState::SENT,
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT};
- // Exposes the protected state fields of the SchedulerStateMachine for testing
- class StateMachine : public SchedulerStateMachine {
- public:
- explicit StateMachine(const SchedulerSettings& scheduler_settings)
- : SchedulerStateMachine(scheduler_settings),
- draw_result_for_test_(DRAW_SUCCESS) {}
- void CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit() {
- DidCreateAndInitializeLayerTreeFrameSink();
- layer_tree_frame_sink_state_ = LayerTreeFrameSinkState::ACTIVE;
- }
- void IssueNextBeginImplFrame() {
- OnBeginImplFrame(viz::BeginFrameId(0, next_begin_frame_number_++),
- kAnimateOnly);
- }
- void SetBeginMainFrameState(BeginMainFrameState cs) {
- begin_main_frame_state_ = cs;
- }
- BeginMainFrameState BeginMainFrameState() const {
- return begin_main_frame_state_;
- }
- ForcedRedrawOnTimeoutState ForcedRedrawState() const {
- return forced_redraw_state_;
- }
- void SetBeginImplFrameState(BeginImplFrameState bifs) {
- begin_impl_frame_state_ = bifs;
- }
- BeginImplFrameState begin_impl_frame_state() const {
- return begin_impl_frame_state_;
- }
- LayerTreeFrameSinkState layer_tree_frame_sink_state() const {
- return layer_tree_frame_sink_state_;
- }
- void SetNeedsBeginMainFrameForTest(bool needs_begin_main_frame) {
- needs_begin_main_frame_ = needs_begin_main_frame;
- }
- bool NeedsCommit() const { return needs_begin_main_frame_; }
- void SetNeedsOneBeginImplFrame(bool needs_frame) {
- needs_one_begin_impl_frame_ = needs_frame;
- }
- void SetNeedsRedraw(bool needs_redraw) { needs_redraw_ = needs_redraw; }
- void SetDrawResultForTest(DrawResult draw_result) {
- draw_result_for_test_ = draw_result;
- }
- DrawResult draw_result_for_test() { return draw_result_for_test_; }
- void SetNeedsForcedRedrawForTimeout(bool b) {
- forced_redraw_state_ = ForcedRedrawOnTimeoutState::WAITING_FOR_COMMIT;
- active_tree_needs_first_draw_ = true;
- }
- bool NeedsForcedRedrawForTimeout() const {
- return forced_redraw_state_ != ForcedRedrawOnTimeoutState::IDLE;
- }
- void SetActiveTreeNeedsFirstDraw(bool needs_first_draw) {
- active_tree_needs_first_draw_ = needs_first_draw;
- }
- bool CanDraw() const { return can_draw_; }
- bool Visible() const { return visible_; }
- bool ShouldAbortCurrentFrame() const {
- return SchedulerStateMachine::ShouldAbortCurrentFrame();
- }
- bool has_pending_tree() const { return has_pending_tree_; }
- void SetHasPendingTree(bool has_pending_tree) {
- has_pending_tree_ = has_pending_tree;
- }
- bool needs_impl_side_invalidation() const {
- return needs_impl_side_invalidation_;
- }
- using SchedulerStateMachine::ProactiveBeginFrameWanted;
- using SchedulerStateMachine::ShouldDraw;
- using SchedulerStateMachine::ShouldPrepareTiles;
- using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately;
- using SchedulerStateMachine::WillCommit;
- protected:
- DrawResult draw_result_for_test_;
- uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
- };
- void PerformAction(StateMachine* sm, SchedulerStateMachine::Action action) {
- switch (action) {
- case SchedulerStateMachine::Action::NONE:
- return;
- case SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE:
- sm->WillActivate();
- return;
- case SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME:
- sm->WillSendBeginMainFrame();
- return;
- case SchedulerStateMachine::Action::
- NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL:
- sm->WillNotifyBeginMainFrameNotExpectedUntil();
- return;
- case SchedulerStateMachine::Action::
- NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON:
- sm->WillNotifyBeginMainFrameNotExpectedSoon();
- return;
- case SchedulerStateMachine::Action::COMMIT: {
- bool commit_has_no_updates = false;
- sm->WillCommit(commit_has_no_updates);
- sm->DidCommit();
- return;
- }
- case SchedulerStateMachine::Action::POST_COMMIT:
- sm->DidPostCommit();
- return;
- case SchedulerStateMachine::Action::DRAW_FORCED:
- case SchedulerStateMachine::Action::DRAW_IF_POSSIBLE: {
- sm->WillDraw();
- sm->DidDraw(sm->draw_result_for_test());
- return;
- }
- case SchedulerStateMachine::Action::DRAW_ABORT: {
- sm->AbortDraw();
- return;
- }
- case SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION:
- sm->WillBeginLayerTreeFrameSinkCreation();
- return;
- case SchedulerStateMachine::Action::PREPARE_TILES:
- sm->WillPrepareTiles();
- return;
- case SchedulerStateMachine::Action::INVALIDATE_LAYER_TREE_FRAME_SINK:
- sm->WillInvalidateLayerTreeFrameSink();
- return;
- case SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION:
- sm->WillPerformImplSideInvalidation();
- return;
- }
- }
- TEST(SchedulerStateMachineTest, BeginFrameNeeded) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::IDLE);
- // Don't request BeginFrames if we are idle.
- state.SetNeedsRedraw(false);
- state.SetNeedsOneBeginImplFrame(false);
- EXPECT_FALSE(state.BeginFrameNeeded());
- // Request BeginFrames if we one is needed.
- state.SetNeedsRedraw(false);
- state.SetNeedsOneBeginImplFrame(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Request BeginFrames if we are ready to draw.
- state.SetVisible(true);
- state.SetNeedsRedraw(true);
- state.SetNeedsOneBeginImplFrame(false);
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Don't background tick for needs_redraw.
- state.SetVisible(false);
- state.SetNeedsRedraw(true);
- state.SetNeedsOneBeginImplFrame(false);
- EXPECT_FALSE(state.BeginFrameNeeded());
- // Proactively request BeginFrames when commit is pending.
- state.SetVisible(true);
- state.SetNeedsRedraw(false);
- state.SetNeedsOneBeginImplFrame(false);
- state.SetNeedsBeginMainFrameForTest(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Don't request BeginFrames when commit is pending if
- // we are currently deferring commits.
- state.SetVisible(true);
- state.SetNeedsRedraw(false);
- state.SetNeedsOneBeginImplFrame(false);
- state.SetNeedsBeginMainFrameForTest(true);
- state.SetDeferBeginMainFrame(true);
- EXPECT_FALSE(state.BeginFrameNeeded());
- }
- TEST(SchedulerStateMachineTest, BeginMainFrameIsHighestPriorityAction) {
- SchedulerSettings default_scheduler_settings;
- default_scheduler_settings.main_frame_before_activation_enabled = true;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- // Still need to active, but sending BMF takes priority.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- // Still need to draw, but sending BMF takes priority.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION(SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest,
- TestNextActionNotifyBeginMainFrameNotExpectedUntil) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetMainThreadWantsBeginMainFrameNotExpectedMessages(true);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- state.IssueNextBeginImplFrame();
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetNeedsOneBeginImplFrame(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::
- NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetNeedsRedraw(true);
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- TestNextActionNotifyBeginMainFrameNotExpectedSoon) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetMainThreadWantsBeginMainFrameNotExpectedMessages(true);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- state.IssueNextBeginImplFrame();
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetNeedsOneBeginImplFrame(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::
- NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetNeedsOneBeginImplFrame(false);
- EXPECT_FALSE(state.BeginFrameNeeded());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetBeginImplFrameState(
- SchedulerStateMachine::BeginImplFrameState::IDLE);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
- SchedulerSettings default_scheduler_settings;
- // If no commit needed, do nothing.
- {
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.SetNeedsRedraw(false);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.NeedsCommit());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.NeedsCommit());
- }
- // If commit requested but not visible yet, do nothing.
- {
- StateMachine state(default_scheduler_settings);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.SetNeedsRedraw(false);
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.NeedsCommit());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.NeedsCommit());
- }
- // If commit requested, begin a main frame.
- {
- StateMachine state(default_scheduler_settings);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetNeedsRedraw(false);
- state.SetNeedsBeginMainFrame();
- // Expect nothing to happen until after OnBeginImplFrame.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BeginImplFrameState::IDLE);
- EXPECT_TRUE(state.NeedsCommit());
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- }
- // If commit requested and can't draw, still begin a main frame.
- {
- StateMachine state(default_scheduler_settings);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetNeedsRedraw(false);
- state.SetNeedsBeginMainFrame();
- state.SetCanDraw(false);
- // Expect nothing to happen until after OnBeginImplFrame.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BeginImplFrameState::IDLE);
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- }
- }
- // Explicitly test main_frame_before_activation_enabled = true
- TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) {
- SchedulerSettings scheduler_settings;
- scheduler_settings.main_frame_before_activation_enabled = true;
- StateMachine state(scheduler_settings);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::IDLE);
- SET_UP_STATE(state);
- state.SetNeedsRedraw(false);
- state.SetNeedsBeginMainFrame();
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Commit to the pending tree.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify that the next commit starts while there is still a pending tree.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify the pending commit doesn't overwrite the pending
- // tree until the pending tree has been activated.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify NotifyReadyToActivate unblocks activation, commit, and
- // draw in that order.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- }
- TEST(SchedulerStateMachineTest,
- FailedDrawForAnimationCheckerboardSetsNeedsCommitAndRetriesDraw) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsRedraw(true);
- EXPECT_TRUE(state.RedrawPending());
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Start a frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.CommitPending());
- // Failing a draw triggers request for a new BeginMainFrame.
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // It's okay to attempt more draws just in case additional raster
- // finishes and the requested commit wasn't actually necessary.
- EXPECT_TRUE(state.CommitPending());
- EXPECT_TRUE(state.RedrawPending());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, FailedDrawForMissingHighResNeedsCommit) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsRedraw(true);
- EXPECT_TRUE(state.RedrawPending());
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Start a frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.CommitPending());
- // Failing a draw triggers because of high res tiles missing
- // request for a new BeginMainFrame.
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // It doesn't request a draw until we get a new commit though.
- EXPECT_TRUE(state.CommitPending());
- EXPECT_FALSE(state.RedrawPending());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Finish the commit and activation.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.RedrawPending());
- // Verify we draw with the new frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_SUCCESS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- TestFailedDrawsEventuallyForceDrawAfterNextCommit) {
- SchedulerSettings scheduler_settings;
- scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced = 1;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Start a commit.
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.CommitPending());
- // Then initiate a draw that fails.
- state.SetNeedsRedraw(true);
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.BeginFrameNeeded());
- EXPECT_TRUE(state.RedrawPending());
- EXPECT_TRUE(state.CommitPending());
- // Finish the commit. Note, we should not yet be forcing a draw, but should
- // continue the commit as usual.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.RedrawPending());
- // Activate so we're ready for a new main frame.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.RedrawPending());
- // The redraw should be forced at the end of the next BeginImplFrame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_SUCCESS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_FORCED);
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestFailedDrawsDoNotRestartForcedDraw) {
- SchedulerSettings scheduler_settings;
- int draw_limit = 2;
- scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced =
- draw_limit;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Start a commit.
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.CommitPending());
- // Then initiate a draw.
- state.SetNeedsRedraw(true);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- // Fail the draw enough times to force a redraw.
- for (int i = 0; i < draw_limit; ++i) {
- state.SetNeedsRedraw(true);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- EXPECT_TRUE(state.BeginFrameNeeded());
- EXPECT_TRUE(state.RedrawPending());
- // But the commit is ongoing.
- EXPECT_TRUE(state.CommitPending());
- EXPECT_TRUE(
- state.ForcedRedrawState() ==
- SchedulerStateMachine::ForcedRedrawOnTimeoutState::WAITING_FOR_COMMIT);
- // After failing additional draws, we should still be in a forced
- // redraw, but not back in IDLE.
- for (int i = 0; i < draw_limit; ++i) {
- state.SetNeedsRedraw(true);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- EXPECT_TRUE(state.RedrawPending());
- EXPECT_TRUE(
- state.ForcedRedrawState() ==
- SchedulerStateMachine::ForcedRedrawOnTimeoutState::WAITING_FOR_COMMIT);
- }
- TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // Start a draw.
- state.SetNeedsRedraw(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_TRUE(state.RedrawPending());
- state.SetDrawResultForTest(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- // Failing the draw for animation checkerboards makes us require a commit.
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.RedrawPending());
- // We should not be trying to draw again now, but we have a commit pending.
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // We should try to draw again at the end of the next BeginImplFrame on
- // the impl thread.
- state.OnBeginImplFrameDeadline();
- state.SetDrawResultForTest(DRAW_SUCCESS);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsRedraw(true);
- // Draw the first frame.
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Before the next BeginImplFrame, set needs redraw again.
- // This should not redraw until the next BeginImplFrame.
- state.SetNeedsRedraw(true);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Move to another frame. This should now draw.
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // We just submitted, so we should proactively request another BeginImplFrame.
- EXPECT_TRUE(state.BeginFrameNeeded());
- }
- TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
- SchedulerSettings default_scheduler_settings;
- // When not in BeginImplFrame deadline, or in BeginImplFrame deadline
- // but not visible, don't draw.
- size_t num_begin_main_frame_states =
- sizeof(begin_main_frame_states) /
- sizeof(SchedulerStateMachine::BeginMainFrameState);
- size_t num_begin_impl_frame_states =
- sizeof(all_begin_impl_frame_states) /
- sizeof(SchedulerStateMachine::BeginImplFrameState);
- for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
- for (size_t j = 0; j < num_begin_impl_frame_states; ++j) {
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginMainFrameState(begin_main_frame_states[i]);
- state.SetBeginImplFrameState(all_begin_impl_frame_states[j]);
- bool visible =
- (all_begin_impl_frame_states[j] !=
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- state.SetVisible(visible);
- // Case 1: needs_begin_main_frame=false
- EXPECT_NE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE,
- state.NextAction());
- // Case 2: needs_begin_main_frame=true
- state.SetNeedsBeginMainFrame();
- EXPECT_NE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE,
- state.NextAction());
- }
- }
- // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw
- // except if we're ready to commit, in which case we expect a commit first.
- for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetCanDraw(true);
- state.SetBeginMainFrameState(begin_main_frame_states[i]);
- state.SetBeginImplFrameState(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- state.SetNeedsRedraw(true);
- SchedulerStateMachine::Action expected_action;
- if (begin_main_frame_states[i] ==
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT) {
- expected_action = SchedulerStateMachine::Action::COMMIT;
- } else {
- expected_action = SchedulerStateMachine::Action::DRAW_IF_POSSIBLE;
- }
- // Case 1: needs_begin_main_frame=false.
- EXPECT_ACTION(expected_action);
- // Case 2: needs_begin_main_frame=true.
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION(expected_action);
- }
- }
- TEST(SchedulerStateMachineTest, TestNoBeginMainFrameStatesRedrawWhenInvisible) {
- SchedulerSettings default_scheduler_settings;
- size_t num_begin_main_frame_states =
- sizeof(begin_main_frame_states) /
- sizeof(SchedulerStateMachine::BeginMainFrameState);
- for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
- // There shouldn't be any drawing regardless of BeginImplFrame.
- for (size_t j = 0; j < 2; ++j) {
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginMainFrameState(begin_main_frame_states[i]);
- state.SetVisible(false);
- state.SetNeedsRedraw(true);
- if (j == 1) {
- state.SetBeginImplFrameState(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- }
- // Case 1: needs_begin_main_frame=false.
- EXPECT_NE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE,
- state.NextAction());
- // Case 2: needs_begin_main_frame=true.
- state.SetNeedsBeginMainFrame();
- EXPECT_NE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE,
- state.NextAction());
- }
- }
- }
- TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
- SchedulerSettings default_scheduler_settings;
- size_t num_begin_main_frame_states =
- sizeof(begin_main_frame_states) /
- sizeof(SchedulerStateMachine::BeginMainFrameState);
- for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
- // There shouldn't be any drawing regardless of BeginImplFrame.
- for (size_t j = 0; j < 2; ++j) {
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginMainFrameState(begin_main_frame_states[i]);
- state.SetVisible(false);
- state.SetNeedsRedraw(true);
- if (j == 1)
- state.IssueNextBeginImplFrame();
- state.SetCanDraw(false);
- EXPECT_NE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE,
- state.NextAction());
- }
- }
- }
- TEST(SchedulerStateMachineTest,
- TestCanRedrawWithWaitingForFirstDrawMakesProgress) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetActiveTreeNeedsFirstDraw(true);
- state.SetNeedsBeginMainFrame();
- state.SetNeedsRedraw(true);
- state.SetCanDraw(false);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestSetNeedsBeginMainFrameIsNotLost) {
- SchedulerSettings scheduler_settings;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- EXPECT_TRUE(state.BeginFrameNeeded());
- // Begin the frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- // Now, while the frame is in progress, set another commit.
- state.SetNeedsBeginMainFrame();
- EXPECT_TRUE(state.NeedsCommit());
- // Let the frame finish.
- state.NotifyReadyToCommit();
- EXPECT_MAIN_FRAME_STATE(
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
- // Expect to commit regardless of BeginImplFrame state.
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_BEGIN_FRAME);
- EXPECT_ACTION(SchedulerStateMachine::Action::COMMIT);
- state.OnBeginImplFrameDeadline();
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- EXPECT_ACTION(SchedulerStateMachine::Action::COMMIT);
- state.OnBeginImplFrameIdle();
- EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BeginImplFrameState::IDLE);
- EXPECT_ACTION(SchedulerStateMachine::Action::COMMIT);
- state.IssueNextBeginImplFrame();
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_BEGIN_FRAME);
- EXPECT_ACTION(SchedulerStateMachine::Action::COMMIT);
- // Finish the commit and activate, then make sure we start the next commit
- // immediately and draw on the next BeginImplFrame.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestFullCycle) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- // Begin the frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Tell the scheduler the frame finished.
- state.NotifyReadyToCommit();
- EXPECT_MAIN_FRAME_STATE(
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
- // Commit.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- // Activate.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_TRUE(state.needs_redraw());
- // Expect to do nothing until BeginImplFrame deadline
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // At BeginImplFrame deadline, draw.
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- // Should be synchronized, no draw needed, no action needed.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_FALSE(state.needs_redraw());
- }
- TEST(SchedulerStateMachineTest, CommitWithoutDrawWithPendingTree) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- // Make a main frame, commit and activate it. But don't draw it.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- // Try to make a new main frame before drawing. Since we will commit it to a
- // pending tree and not clobber the active tree, we're able to start a new
- // begin frame and commit it.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- }
- TEST(SchedulerStateMachineTest, DontCommitWithoutDrawWithoutPendingTree) {
- SchedulerSettings scheduler_settings;
- scheduler_settings.commit_to_active_tree = true;
- scheduler_settings.main_frame_before_activation_enabled = false;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- // Make a main frame, commit and activate it. But don't draw it.
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- // Try to make a new main frame before drawing, but since we would clobber the
- // active tree, we will not do so.
- state.SetNeedsBeginMainFrame();
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, AbortedMainFrameDoesNotResetPendingTree) {
- SchedulerSettings scheduler_settings;
- scheduler_settings.main_frame_before_activation_enabled = true;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Perform a commit so that we have an active tree.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.has_pending_tree());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Ask for another commit but abort it. Verify that we didn't reset pending
- // tree state.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.has_pending_tree());
- state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.has_pending_tree());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Ask for another commit that doesn't abort.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.has_pending_tree());
- // Verify that commit is delayed until the pending tree is activated.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_FALSE(state.has_pending_tree());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.has_pending_tree());
- }
- TEST(SchedulerStateMachineTest, TestFullCycleWithCommitToActive) {
- SchedulerSettings scheduler_settings;
- scheduler_settings.commit_to_active_tree = true;
- scheduler_settings.main_frame_before_activation_enabled = false;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- // Begin the frame.
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Tell the scheduler the frame finished.
- state.NotifyReadyToCommit();
- EXPECT_MAIN_FRAME_STATE(
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
- // Commit.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- // Commit always calls NotifyReadyToActivate in this mode.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // No draw because we haven't received NotifyReadyToDraw yet.
- state.OnBeginImplFrameDeadline();
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_TRUE(state.needs_redraw());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Can't BeginMainFrame yet since last commit hasn't been drawn yet.
- state.SetNeedsBeginMainFrame();
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Now call ready to draw which will allow the draw to happen and
- // BeginMainFrame to be sent.
- state.NotifyReadyToDraw();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- // Submit throttled from this point.
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Can't BeginMainFrame yet since we're submit-frame throttled.
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // CompositorFrameAck unblocks BeginMainFrame.
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Draw the newly activated tree.
- state.NotifyReadyToDraw();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // When commits are deferred, we don't block the deadline.
- state.SetDeferBeginMainFrame(true);
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_NE(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- }
- TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- // Begin the frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Request another commit while the commit is in flight.
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Tell the scheduler the frame finished.
- state.NotifyReadyToCommit();
- EXPECT_MAIN_FRAME_STATE(
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
- // First commit and activate.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_TRUE(state.needs_redraw());
- // Expect to do nothing until BeginImplFrame deadline.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // At BeginImplFrame deadline, draw.
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- // Should be synchronized, no draw needed, no action needed.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_FALSE(state.needs_redraw());
- // Next BeginImplFrame should initiate second commit.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest, TestNoRequestCommitWhenInvisible) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetVisible(false);
- state.SetNeedsBeginMainFrame();
- EXPECT_FALSE(state.CouldSendBeginMainFrame());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestNoRequestCommitWhenBeginFrameSourcePaused) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginFrameSourcePaused(true);
- state.SetNeedsBeginMainFrame();
- EXPECT_FALSE(state.CouldSendBeginMainFrame());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestNoRequestLayerTreeFrameSinkWhenInvisible) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- // We should not request a LayerTreeFrameSink when we are still invisible.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetVisible(false);
- state.DidLoseLayerTreeFrameSink();
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- }
- // See ProxyMain::BeginMainFrame "EarlyOut_NotVisible" /
- // "EarlyOut_LayerTreeFrameSinkLost" cases.
- TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- // Begin the frame while visible.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Become invisible and abort BeginMainFrame.
- state.SetVisible(false);
- state.BeginMainFrameAborted(CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
- // NeedsCommit should now be true again because we never actually did a
- // commit.
- EXPECT_TRUE(state.NeedsCommit());
- // We should now be back in the idle state as if we never started the frame.
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // We shouldn't do anything on the BeginImplFrame deadline.
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Become visible again.
- state.SetVisible(true);
- // Although we have aborted on this frame and haven't cancelled the commit
- // (i.e. need another), don't send another BeginMainFrame yet.
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.NeedsCommit());
- // Start a new frame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- // We should be starting the commit now.
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- // See ProxyMain::BeginMainFrame "EarlyOut_NoUpdates" case.
- TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.DidCreateAndInitializeLayerTreeFrameSink();
- state.SetCanDraw(true);
- // Get into a begin frame / commit state.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- // Abort the commit, true means that the BeginMainFrame was sent but there
- // was no work to do on the main thread.
- state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
- // NeedsCommit should now be false because the commit was actually handled.
- EXPECT_FALSE(state.NeedsCommit());
- // Since the commit was aborted, we don't need to try and draw.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify another commit doesn't start on another frame either.
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify another commit can start if requested, though.
- state.SetNeedsBeginMainFrame();
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION(SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- state.SetCanDraw(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Check that the first init does not SetNeedsBeginMainFrame.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Check that a needs commit initiates a BeginMainFrame.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- EXPECT_NE(SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION,
- state.NextAction());
- state.DidLoseLayerTreeFrameSink();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Once context recreation begins, nothing should happen.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Recreate the context.
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- // When the context is recreated, we should begin a commit.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest,
- TestContextLostWhenIdleAndCommitRequestedWhileRecreating) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- EXPECT_NE(SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION,
- state.NextAction());
- state.DidLoseLayerTreeFrameSink();
- EXPECT_EQ(state.layer_tree_frame_sink_state(),
- SchedulerStateMachine::LayerTreeFrameSinkState::NONE);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Once context recreation begins, nothing should happen.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // While context is recreating, commits shouldn't begin.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Recreate the context
- state.DidCreateAndInitializeLayerTreeFrameSink();
- EXPECT_EQ(
- state.layer_tree_frame_sink_state(),
- SchedulerStateMachine::LayerTreeFrameSinkState::WAITING_FOR_FIRST_COMMIT);
- EXPECT_FALSE(state.RedrawPending());
- // When the context is recreated, we wait until the next BeginImplFrame
- // before starting.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // When the BeginFrame comes in we should begin a commit
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- // Until that commit finishes, we shouldn't be drawing.
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Finish the commit, which should make the surface active.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_EQ(state.layer_tree_frame_sink_state(),
- SchedulerStateMachine::LayerTreeFrameSinkState::
- WAITING_FOR_FIRST_ACTIVATION);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_EQ(state.layer_tree_frame_sink_state(),
- SchedulerStateMachine::LayerTreeFrameSinkState::ACTIVE);
- // Finishing the first commit after initializing a LayerTreeFrameSink should
- // automatically cause a redraw.
- EXPECT_TRUE(state.RedrawPending());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.RedrawPending());
- // Next frame as no work to do.
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Once the context is recreated, whether we draw should be based on
- // SetCanDraw if waiting on first draw after activate.
- state.SetNeedsRedraw(true);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.SetCanDraw(false);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- state.SetCanDraw(true);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Once the context is recreated, whether we draw should be based on
- // SetCanDraw if waiting on first draw after activate.
- state.SetNeedsRedraw(true);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Activate so we need the first draw
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_TRUE(state.needs_redraw());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.SetCanDraw(false);
- EXPECT_ACTION(SchedulerStateMachine::Action::DRAW_ABORT);
- state.SetCanDraw(true);
- EXPECT_ACTION(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- }
- TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) {
- SchedulerSettings scheduler_settings;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Get a commit in flight.
- state.SetNeedsBeginMainFrame();
- // Set damage and expect a draw.
- state.SetNeedsRedraw(true);
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Cause a lost context while the BeginMainFrame is in flight.
- state.DidLoseLayerTreeFrameSink();
- EXPECT_FALSE(state.BeginFrameNeeded());
- // Ask for another draw. Expect nothing happens.
- state.SetNeedsRedraw(true);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- // Finish the frame, commit and activate.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- // We will abort the draw when the LayerTreeFrameSink is lost if we are
- // waiting for the first draw to unblock the main thread.
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- // Expect to begin context recreation only in BeginImplFrameState::IDLE
- EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BeginImplFrameState::IDLE);
- EXPECT_ACTION(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_BEGIN_FRAME);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- TestContextLostWhileCommitInProgressAndAnotherCommitRequested) {
- SchedulerSettings scheduler_settings;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Get a commit in flight.
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Set damage and expect a draw.
- state.SetNeedsRedraw(true);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Cause a lost context while the BeginMainFrame is in flight.
- state.DidLoseLayerTreeFrameSink();
- // Ask for another draw and also set needs commit. Expect nothing happens.
- state.SetNeedsRedraw(true);
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Finish the frame, and commit and activate.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- // Because the LayerTreeFrameSink is missing, we expect the draw to abort.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- // Expect to begin context recreation only in BeginImplFrameState::IDLE
- EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BeginImplFrameState::IDLE);
- EXPECT_ACTION(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- state.IssueNextBeginImplFrame();
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_BEGIN_FRAME);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- // After we get a new LayerTreeFrameSink, the commit flow should start.
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- DontDrawBeforeCommitAfterLostLayerTreeFrameSink) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsRedraw(true);
- // Cause a lost LayerTreeFrameSink, and restore it.
- state.DidLoseLayerTreeFrameSink();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.DidCreateAndInitializeLayerTreeFrameSink();
- EXPECT_FALSE(state.RedrawPending());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION(SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest,
- TestShouldAbortCurrentFrameAfterLostLayerTreeFrameSink) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::SENT);
- // Cause a lost context.
- state.DidLoseLayerTreeFrameSink();
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_TRUE(state.ShouldAbortCurrentFrame());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- }
- TEST(SchedulerStateMachineTest, TestNoBeginFrameNeededWhenInvisible) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- EXPECT_FALSE(state.BeginFrameNeeded());
- state.SetNeedsRedraw(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.SetVisible(false);
- EXPECT_FALSE(state.BeginFrameNeeded());
- state.SetVisible(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- }
- TEST(SchedulerStateMachineTest, TestNoBeginMainFrameWhenInvisible) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetVisible(false);
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.BeginFrameNeeded());
- // When become visible again, the needs commit should still be pending.
- state.SetVisible(true);
- EXPECT_TRUE(state.BeginFrameNeeded());
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetVisible(false);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::SENT);
- state.SetNeedsBeginMainFrame();
- // After the commit completes, activation and draw happen immediately
- // because we are not visible.
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- TestFinishCommitWhenCommitInProgressAndBeginFrameSourcePaused) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- state.SetVisible(true);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.CreateAndInitializeLayerTreeFrameSinkWithActivatedCommit();
- state.SetBeginFrameSourcePaused(true);
- state.SetBeginMainFrameState(
- SchedulerStateMachine::BeginMainFrameState::SENT);
- state.SetNeedsBeginMainFrame();
- // After the commit completes, activation and draw happen immediately
- // because we are not visible.
- state.NotifyReadyToCommit();
- EXPECT_TRUE(state.ShouldAbortCurrentFrame());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_ABORT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.DidLoseLayerTreeFrameSink();
- // When we are visible, we normally want to begin LayerTreeFrameSink creation
- // as soon as possible.
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- state.DidCreateAndInitializeLayerTreeFrameSink();
- EXPECT_EQ(
- state.layer_tree_frame_sink_state(),
- SchedulerStateMachine::LayerTreeFrameSinkState::WAITING_FOR_FIRST_COMMIT);
- // We should not send a BeginMainFrame when we are invisible, even if we've
- // lost the LayerTreeFrameSink and are trying to get the first commit, since
- // the
- // main thread will just abort anyway.
- state.SetVisible(false);
- EXPECT_ACTION(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(false);
- state.SetVisible(true);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(true);
- state.SetVisible(false);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(false);
- state.SetVisible(false);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(true);
- state.SetVisible(true);
- state.SetBeginFrameSourcePaused(true);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetBeginFrameSourcePaused(false);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- }
- TEST(SchedulerStateMachineTest, ForceDrawForResourcelessSoftwareDraw) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetResourcelessSoftwareDraw(true);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetVisible(false);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetResourcelessSoftwareDraw(false);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetResourcelessSoftwareDraw(true);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetVisible(true);
- state.SetBeginFrameSourcePaused(true);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetResourcelessSoftwareDraw(false);
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetResourcelessSoftwareDraw(true);
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetBeginFrameSourcePaused(false);
- state.SetVisible(false);
- state.DidLoseLayerTreeFrameSink();
- state.SetCanDraw(false);
- state.WillBeginLayerTreeFrameSinkCreation();
- state.DidCreateAndInitializeLayerTreeFrameSink();
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(true);
- state.DidLoseLayerTreeFrameSink();
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(true);
- state.WillBeginLayerTreeFrameSinkCreation();
- state.DidCreateAndInitializeLayerTreeFrameSink();
- EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
- state.SetCanDraw(false);
- state.DidLoseLayerTreeFrameSink();
- EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
- }
- TEST(SchedulerStateMachineTest,
- TestTriggerDeadlineImmediatelyAfterAbortedCommit) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // This test mirrors what happens during the first frame of a scroll gesture.
- // First we get the input event and a BeginFrame.
- state.IssueNextBeginImplFrame();
- // As a response the compositor requests a redraw and a commit to tell the
- // main thread about the new scroll offset.
- state.SetNeedsRedraw(true);
- state.SetNeedsBeginMainFrame();
- // We should start the commit normally.
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Since only the scroll offset changed, the main thread will abort the
- // commit.
- state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
- // Since the commit was aborted, we should draw right away instead of waiting
- // for the deadline.
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- }
- void FinishPreviousCommitAndDrawWithoutExitingDeadline(
- StateMachine* state_ptr) {
- // Gross, but allows us to use macros below.
- StateMachine& state = *state_ptr;
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- }
- TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // This test ensures that impl-draws are prioritized over main thread updates
- // in prefer impl latency mode.
- state.SetNeedsRedraw(true);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify the deadline is not triggered early until we enter
- // prefer impl latency mode.
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.SetTreePrioritiesAndScrollState(
- SMOOTHNESS_TAKES_PRIORITY,
- ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- // Trigger the deadline.
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.DidReceiveCompositorFrameAck();
- // Request a new commit and finish the previous one.
- state.SetNeedsBeginMainFrame();
- FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Finish the previous commit and draw it.
- FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Verify we do not send another BeginMainFrame if was are submit-frame
- // throttled and did not just submit one.
- state.SetNeedsBeginMainFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- TestTriggerDeadlineImmediatelyOnLostLayerTreeFrameSink) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.DidLoseLayerTreeFrameSink();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // The deadline should be triggered immediately when LayerTreeFrameSink is
- // lost.
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- }
- TEST(SchedulerStateMachineTest, TestTriggerDeadlineImmediatelyWhenInvisible) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.SetVisible(false);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.ShouldAbortCurrentFrame());
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- }
- TEST(SchedulerStateMachineTest,
- TestTriggerDeadlineImmediatelyWhenBeginFrameSourcePaused) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- state.SetBeginFrameSourcePaused(true);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_TRUE(state.ShouldAbortCurrentFrame());
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- }
- TEST(SchedulerStateMachineTest, TestDeferBeginMainFrame) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- state.SetDeferBeginMainFrame(true);
- state.SetNeedsBeginMainFrame();
- EXPECT_FALSE(state.BeginFrameNeeded());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetDeferBeginMainFrame(false);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- }
- TEST(SchedulerStateMachineTest, EarlyOutCommitWantsProactiveBeginFrame) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- EXPECT_FALSE(state.ProactiveBeginFrameWanted());
- bool commit_has_no_updates = true;
- state.WillCommit(commit_has_no_updates);
- EXPECT_TRUE(state.ProactiveBeginFrameWanted());
- state.IssueNextBeginImplFrame();
- EXPECT_FALSE(state.ProactiveBeginFrameWanted());
- }
- TEST(SchedulerStateMachineTest,
- NoLayerTreeFrameSinkCreationWhileCommitPending) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Set up the request for a commit and start a frame.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- PerformAction(&state, SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- // Lose the LayerTreeFrameSink.
- state.DidLoseLayerTreeFrameSink();
- // The scheduler shouldn't trigger the LayerTreeFrameSink creation till the
- // previous commit has been cleared.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Trigger the deadline and ensure that the scheduler does not trigger any
- // actions until we receive a response for the pending commit.
- state.OnBeginImplFrameDeadline();
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Abort the commit, since that is what we expect the main thread to do if the
- // LayerTreeFrameSink was lost due to a synchronous call from the main thread
- // to release the LayerTreeFrameSink.
- state.BeginMainFrameAborted(CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
- // The scheduler should begin the LayerTreeFrameSink creation now.
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- }
- TEST(SchedulerStateMachineTest, NoImplSideInvalidationsWhileInvisible) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // No impl-side invalidations should be performed while we are not visible.
- state.SetVisible(false);
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- NoImplSideInvalidationsWhenBeginFrameSourcePaused) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // No impl-side invalidations should be performed while we can not make impl
- // frames.
- state.SetBeginFrameSourcePaused(true);
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- ImplSideInvalidationAndMainFrame_NoMainFrameRequest) {
- // No main frame request or any update in the last frame, invalidation runs
- // immediately.
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest,
- ImplSideInvalidationAndMainFrame_MainFrameRequest_FastMainThread) {
- // Main frame request, no abort history and the main thread is fast,
- // invalidation waits for main frame.
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- bool needs_first_draw_on_activation = true;
- state.set_should_defer_invalidation_for_fast_main_frame(true);
- state.SetNeedsBeginMainFrame();
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- ImplSideInvalidationAndMainFrame_LastFrameCommit) {
- // Main frame committed in the last impl frame and is fast, invalidation waits
- // for main frame request.
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- bool needs_first_draw_on_activation = true;
- state.set_should_defer_invalidation_for_fast_main_frame(true);
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest,
- ImplSideInvalidationAndMainFrame_LastFrameAborted) {
- // Last main frame was aborted. An invalidation is performed even if a main
- // frame request is pending.
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- bool needs_first_draw_on_activation = true;
- state.set_should_defer_invalidation_for_fast_main_frame(true);
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest,
- ImplSideInvalidationAndMainFrame_MainFrameRequest_SlowMainThread) {
- // Main frame request but the main thread is slow, invalidation runs
- // immediately.
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- bool needs_first_draw_on_activation = true;
- state.set_should_defer_invalidation_for_fast_main_frame(false);
- state.SetNeedsBeginMainFrame();
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest, NoImplSideInvalidationUntilFrameSinkActive) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Prefer impl side invalidation over begin main frame.
- state.set_should_defer_invalidation_for_fast_main_frame(false);
- state.DidLoseLayerTreeFrameSink();
- // Create new frame sink but don't commit or activate yet.
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION);
- state.DidCreateAndInitializeLayerTreeFrameSink();
- state.SetNeedsBeginMainFrame();
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- // No impl side invalidation because we're still waiting for first commit.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.OnBeginImplFrameDeadline();
- state.OnBeginImplFrameIdle();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- // No impl side invalidation because we're still waiting for first activation.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.OnBeginImplFrameIdle();
- state.SetNeedsBeginMainFrame();
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- // Impl side invalidation only after receiving first commit and activation for
- // new frame sink.
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest, ImplSideInvalidationWhenPendingTreeExists) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Set up request for the main frame, commit and create the pending tree.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- // Request an impl-side invalidation after the commit. The request should wait
- // till the current pending tree is activated.
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Activate the pending tree. Since the commit fills the impl-side
- // invalidation funnel as well, the request should wait until the next
- // BeginFrame.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Since there is no main frame request, this should perform impl-side
- // invalidations.
- state.set_should_defer_invalidation_for_fast_main_frame(false);
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest, ImplSideInvalidationWhileReadyToCommit) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Set up request for the main frame with a slow main thread.
- state.set_should_defer_invalidation_for_fast_main_frame(false);
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToCommit();
- // Request an impl-side invalidation after we are ready to commit. The
- // invalidations are merged.
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- EXPECT_TRUE(state.needs_impl_side_invalidation());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_FALSE(state.needs_impl_side_invalidation());
- }
- TEST(SchedulerStateMachineTest,
- ConsecutiveImplSideInvalidationsWaitForBeginFrame) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Set up a request for impl-side invalidation.
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Request another invalidation, which should wait until the pending tree is
- // activated *and* we start the next BeginFrame.
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Now start the next frame, which will first draw the active tree and then
- // perform the pending impl-side invalidation request.
- state.IssueNextBeginImplFrame();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest, ImplSideInvalidationsThrottledOnDraw) {
- // In commit_to_active_tree mode, performing the next invalidation should be
- // throttled on the active tree being drawn.
- SchedulerSettings settings;
- settings.commit_to_active_tree = true;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Commit to the sync tree, activate and draw.
- state.SetNeedsBeginMainFrame();
- state.IssueNextBeginImplFrame();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.NotifyReadyToDraw();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Request impl-side invalidation and start a new frame, which should be
- // blocked on the ack for the previous frame.
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.IssueNextBeginImplFrame();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Ack the previous frame and begin impl frame, which should perform the
- // invalidation now.
- state.DidReceiveCompositorFrameAck();
- state.IssueNextBeginImplFrame();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- }
- TEST(SchedulerStateMachineTest, PrepareTilesWaitForImplSideInvalidation) {
- // PrepareTiles
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Request a PrepareTiles and impl-side invalidation. The impl-side
- // invalidation should run first, since it will perform PrepareTiles as well.
- bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.SetNeedsPrepareTiles();
- state.IssueNextBeginImplFrame();
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- state.DidPrepareTiles();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- }
- TEST(SchedulerStateMachineTest, TestFullPipelineMode) {
- SchedulerSettings scheduler_settings;
- scheduler_settings.wait_for_all_pipeline_stages_before_draw = true;
- StateMachine state(scheduler_settings);
- SET_UP_STATE(state);
- // Start clean and set commit.
- state.SetNeedsBeginMainFrame();
- // While we are waiting for an main frame or pending tree activation, we
- // should even block while we can't draw.
- state.SetCanDraw(false);
- // Begin the frame.
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- // If main thread defers commits, don't wait for it.
- state.SetDeferBeginMainFrame(true);
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- state.SetDeferBeginMainFrame(false);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
- EXPECT_FALSE(state.NeedsCommit());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // We are blocking on the main frame.
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- // Tell the scheduler the frame finished.
- state.NotifyReadyToCommit();
- EXPECT_MAIN_FRAME_STATE(
- SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
- // We are blocking on commit.
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- // Commit.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- // We are blocking on activation.
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // We should prepare tiles even though we are not in the deadline, otherwise
- // we would get stuck here.
- EXPECT_FALSE(state.ShouldPrepareTiles());
- state.SetNeedsPrepareTiles();
- EXPECT_TRUE(state.ShouldPrepareTiles());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::PREPARE_TILES);
- // Ready to activate, but not draw.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- // We should no longer block, because can_draw is still false, and we are no
- // longer waiting for activation.
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- // However, we should continue to block on ready to draw if we can draw.
- state.SetCanDraw(true);
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Ready to draw triggers immediate deadline.
- state.NotifyReadyToDraw();
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // In full-pipe mode, CompositorFrameAck should always arrive before any
- // subsequent BeginFrame.
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Request a redraw without main frame.
- state.SetNeedsRedraw(true);
- // Redraw should happen immediately since there is no pending tree and active
- // tree is ready to draw.
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- // Redraw on impl-side only.
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.DidSubmitCompositorFrame();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // In full-pipe mode, CompositorFrameAck should always arrive before any
- // subsequent BeginFrame.
- state.DidReceiveCompositorFrameAck();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Request a redraw on active frame and a main frame.
- state.SetNeedsRedraw(true);
- state.SetNeedsBeginMainFrame();
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Blocked on main frame.
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- // Even with SMOOTHNESS_TAKES_PRIORITY, we don't prioritize impl thread and we
- // should wait for main frame.
- state.SetTreePrioritiesAndScrollState(
- SMOOTHNESS_TAKES_PRIORITY,
- ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED,
- state.CurrentBeginImplFrameDeadlineMode());
- // Abort commit and ensure that we don't block anymore.
- state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- }
- TEST(SchedulerStateMachineTest, AllowSkippingActiveTreeFirstDraws) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Impl-side invalidation creates a pending tree which is activated but not
- // drawn in this frame.
- bool needs_first_draw_on_activation = false;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 1);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.OnBeginImplFrameIdle();
- // Now we have a main frame.
- state.SetNeedsBeginMainFrame();
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- // We should be able to activate this tree without drawing the active tree.
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- }
- TEST(SchedulerStateMachineTest, DelayDrawIfAnimationWorkletsPending) {
- SchedulerSettings default_scheduler_settings;
- StateMachine state(default_scheduler_settings);
- SET_UP_STATE(state);
- // This test verifies that having pending mutations from Animation Worklets on
- // the active tree will not trigger the deadline early.
- state.SetNeedsBeginMainFrame();
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- // Started async mutation cycle for animation worklets.
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::PROCESSING,
- SchedulerStateMachine::TreeType::ACTIVE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR,
- state.CurrentBeginImplFrameDeadlineMode());
- // Second queued state change.
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::PROCESSING,
- SchedulerStateMachine::TreeType::ACTIVE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR,
- state.CurrentBeginImplFrameDeadlineMode());
- // First mutation cycle completes. Still waiting on queued mutation cycle
- // before being ready to draw.
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::IDLE,
- SchedulerStateMachine::TreeType::ACTIVE);
- EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR,
- state.CurrentBeginImplFrameDeadlineMode());
- // Queued mutation cycle completes. Now ready to draw.
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::IDLE,
- SchedulerStateMachine::TreeType::ACTIVE);
- EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
- EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
- state.CurrentBeginImplFrameDeadlineMode());
- // AnimationWorkletState does not effect CanDraw, only whether an early draw
- // deadline should be used (crbug/937975).
- state.SetNeedsRedraw(true);
- state.OnBeginImplFrameDeadline();
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE);
- EXPECT_TRUE(state.ShouldDraw());
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::PROCESSING,
- SchedulerStateMachine::TreeType::ACTIVE);
- EXPECT_TRUE(state.ShouldDraw());
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::IDLE,
- SchedulerStateMachine::TreeType::ACTIVE);
- EXPECT_TRUE(state.ShouldDraw());
- }
- TEST(SchedulerStateMachineTest, BlockActivationIfAnimationWorkletsPending) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- // Verify that pending mutations from Animation Worklets block activation.
- state.SetNeedsBeginMainFrame();
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::PROCESSING,
- SchedulerStateMachine::TreeType::PENDING);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyAnimationWorkletStateChange(
- SchedulerStateMachine::AnimationWorkletState::IDLE,
- SchedulerStateMachine::TreeType::PENDING);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- }
- TEST(SchedulerStateMachineTest, BlockActivationIfPaintWorkletsPending) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Post-commit, we start working on PaintWorklets. It is not valid to activate
- // until they are done.
- state.NotifyPaintWorkletStateChange(
- SchedulerStateMachine::PaintWorkletState::PROCESSING);
- // We (correctly) cannot call state.NotifyReadyToActivate() here as it hits a
- // DCHECK because PaintWorklets are ongoing.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyPaintWorkletStateChange(
- SchedulerStateMachine::PaintWorkletState::IDLE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- }
- TEST(SchedulerStateMachineTest,
- BlockActivationIfPaintWorkletsPendingEvenWhenAbortingFrame) {
- SchedulerSettings settings;
- StateMachine state(settings);
- SET_UP_STATE(state);
- state.SetNeedsBeginMainFrame();
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- // Even if we are aborting the frame, we must paint the pending tree before we
- // activate it (because we cannot have an unpainted active tree).
- state.NotifyPaintWorkletStateChange(
- SchedulerStateMachine::PaintWorkletState::PROCESSING);
- state.SetVisible(false);
- ASSERT_TRUE(state.ShouldAbortCurrentFrame());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyPaintWorkletStateChange(
- SchedulerStateMachine::PaintWorkletState::IDLE);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- }
- TEST(SchedulerStateMachineTest, TestFullPipelineModeDoesntBlockAfterCommit) {
- SchedulerSettings settings;
- settings.wait_for_all_pipeline_stages_before_draw = true;
- StateMachine state(settings);
- SET_UP_STATE(state);
- const bool needs_first_draw_on_activation = true;
- state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
- state.SetNeedsBeginMainFrame();
- state.SetNeedsRedraw(true);
- viz::BeginFrameId frame_id = viz::BeginFrameId(0, 10);
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
- state.NotifyReadyToActivate();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
- state.NotifyReadyToDraw();
- EXPECT_TRUE(state.active_tree_needs_first_draw());
- EXPECT_IMPL_FRAME_STATE(
- SchedulerStateMachine::BeginImplFrameState::INSIDE_BEGIN_FRAME);
- // Go all the way until ready to draw, but make sure we're not within
- // the frame deadline, so actual draw doesn't happen...
- EXPECT_FALSE(state.ShouldDraw());
- // ... then have another commit ...
- state.SetNeedsBeginMainFrame();
- frame_id.sequence_number++;
- state.OnBeginImplFrame(frame_id, kAnimateOnly);
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
- state.NotifyReadyToCommit();
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
- // ... and make sure we're in a state where we can proceed,
- // rather than draw being blocked by the pending tree.
- state.OnBeginImplFrameDeadline();
- EXPECT_TRUE(state.ShouldDraw());
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
- }
- } // namespace
- } // namespace cc
|