一次图2所示的第3个操作ACTION_COMMIT,以便补充缺失的分块。
ACTION_COMMIT操作执行完成之后,如果Main线程在绘制网页时,仅仅记录了CC Layer Tree的绘制命令,也就是前面提到的impl_side_painting等于true,那么就意味着存在一个CC Pending Layer Tree,这时候网页渲染状态会被设置为FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,表示等待CC Pending Layer Tree被激活为CC Active Layer Tree。
另一方面,ACTION_COMMIT操作执行完成之后,如果Main线程在绘制网页时,直接进行光栅化,也就是前面提到的impl_side_painting等于false,那么就意味着不会存在一个CC Pending Layer Tree,这时候网页渲染状态会被设置为FORCED_REDRAW_STATE_WAITING_FOR_DRAW,表示等待CC Active Layer Tree被渲染。
如果网页渲染状态被设置为FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,那么当图2所示的第5个操作ACTION_ACTIVATE_PENDING_TREE执行完成之后。也就是CC Pending Layer Tree被激活为CC Active Layer Tree之后,网页渲染状态会被设置为FORCED_REDRAW_STATE_WAITING_FOR_DRAW,表示等待CC Active Layer Tree被渲染。
当CC Active Layer Tree被渲染之后,网页渲染状态就会从FORCED_REDRAW_STATE_WAITING_FOR_DRAW变为FORCED_REDRAW_STATE_IDLE状态。
理解了网页的BeginImplFrameState、OutputSurfaceState、CommitState和ForcedRedrawOnTimeoutState状态之后,接下来我们就可以分析调度器的实现了,也就是调度器的执行过程。
调度器通过Scheduler类实现,调度器的执行过程就表现为Scheduler类的成员函数ProcessScheduledActions不断地被调用,如下所示:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 void Scheduler::ProcessScheduledActions() { ......
SchedulerStateMachine::Action action; do {
action = state_machine_.NextAction(); ......
state_machine_.UpdateState(action);
base::AutoReset
case SchedulerStateMachine::ACTION_NONE: break;
case SchedulerStateMachine::ACTION_ANIMATE: client_->ScheduledActionAnimate(); break;
case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: client_->ScheduledActionSendBeginMainFrame(); break;
case SchedulerStateMachine::ACTION_COMMIT: client_->ScheduledActionCommit(); break;
case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES: client_->ScheduledActionUpdateVisibleTiles(); break;
case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE: client_->ScheduledActionActivatePendingTree(); break;
case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: DrawAndSwapIfPossible(); break;
case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: client_->ScheduledActionDrawAndSwapForced(); break;
case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: // No action is actually performed, but this allows the state machine to // advance out of its waiting to draw state without actually drawing. break;
case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: client_->ScheduledActionBeginOutputSurfaceCreation(); break;
case SchedulerStateMachine::ACTION_MANAGE_TILES: client_->ScheduledActionManageTiles(); break; }
} while (action != SchedulerStateMachine::ACTION_NONE);
SetupNextBeginFrameIfNeeded(); ......
if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { ......
ScheduleBeginImplFrameDeadline(base::TimeTicks()); } }
这个函数定义在文件external/chromium_org/cc/scheduler/scheduler.cc中。
Scheduler类的成员函数ProcessScheduledActions在一个while循环中不断地调用成员变量state_machine_指向的SchedulerStateMachine对象的成员函数NextAction询问状态机下一个要执行的操作,直到状态机告知当前没有操作要执行为止。这些操作大概就对应于图2所示的操作。
每一个操作都是通过调用成员变量client_指向的ThreadProxy对象对应的成员函数执行的。例如,ACTION_SEND_BEGIN_MAIN_FRAME操作是通过调用成员变量client_指向的ThreadProxy对象的成员函数ScheduledActionSendBeginMainFrame执行的。ThreadProxy类的这些函数我们在后面的文章中再详细分析。每一个操作在执行之前,Scheduler类的成员函数ProcessScheduledActions会先调用state_machine_指向的SchedulerStateMachine对象的成员函数UpdateState更新状态机的状态。
跳出while循环之后,Scheduler类的成员函数ProcessScheduledActions调用另外一个成员函数SetupNextBeginFrameIfNeeded根据状态机的当前状态决定是否要发起下一个BEGIN_IMPL_FRAME操作。如果需要的话,就会在下一个VSync信号到来时,通过调用Scheduler类的成员函数ProcessScheduledActions渲染网页的下一帧。
Scheduler类的成员函数ProcessScheduledActions最后还会调用成员变量state_machine_指向的SchedulerStateMachine对象的成员函数ShouldTriggerBeginImplFrameDeadlineEarly检查是否提前执行渲染网页的操作。如果需要提前的话,那么就不会等待上一个VSync信号到来时设置的Deadline到期,而是马上调用成员函数ScheduleBeginImplFrameDeadline假设该Deadline已经到期,于是就可以马上渲染网页。
为了更好地理解调度器的执行过程,接下来我们继续前面提到的SchedulerStateMachine类的成员函数NextAction、UpdateState和ShouldTriggerBeginImplFrameDeadlineEarly以及Scheduler类的成员函数SetupNextBeginFrameIfNeeded和ScheduleBeginImplFrameDeadline的实现。
SchedulerStateMachine类的成员函数NextAction的实现如下所示:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { if (ShouldUpdateVisibleTiles())
return ACTION_UPDATE_VISIBLE_TILES; if (ShouldActivatePendingTree())
return ACTION_ACTIVATE_PENDING_TREE; if (ShouldCommit())
return ACTION_COMMIT; if (ShouldAnimate())
return ACTION_ANIMATE; if (ShouldDraw()) {
if (PendingDrawsShouldBeAborted())
return ACTION_DRAW_AND_SWAP_ABORT;
else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) return ACTION_DRAW_AND_SWAP_FORCED; else
return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; }
if (ShouldManageTiles())
return ACTION_MANAGE_TILES; if (ShouldSendBeginMainFrame())
return ACTION_SEND_BEGIN_MAIN_FRAME; if (ShouldBeginOutputSurfaceCreation())
return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; return ACTION_NONE; }
这个函数定义在文件external/chromium_org/cc/scheduler/scheduler_state_machine.cc中。
SchedulerStateMachine类的成员函数NextAction通过调用一系列的成员函数ShouldXXX决定当前需要执行的操作。例如,如果调用成员函数ShouldCommit得到的返回值为true,那么就SchedulerStateMachine类的成员函数NextAction就会返回一个ACTION_COMMIT值表示要执行一个ACTION_COMMIT操作。这些ShouldXXX成员函数我们在后面的文章中再详细分析。
SchedulerStateMachine类的成员函数UpdateState的实现如下所示:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 void SchedulerStateMachine::UpdateState(Action action) { switch (action) {
case ACTION_NONE: return;
case ACTION_UPDATE_VISIBLE_TILES:
last_frame_number_update_visible_tiles_was_called_ = current_frame_number_; return;
case ACTION_ACTIVATE_PENDING_TREE: UpdateStateOnActivation(); return;
case ACTION_ANIMATE:
last_frame_number_animate_performed_ = current_frame_number_; needs_animate_ = false;
// TODO(skyostil): Instead of assuming this, require the client to tell // us.
SetNeedsRedraw(); return;
case ACTION_SEND_BEGIN_MAIN_FRAME: DCHECK(!has_pending_tree_ ||
settings_.main_frame_before_activation_enabled); DCHECK(!active_tree_needs_first_draw_ ||
settings_.main_frame_before_draw_enabled); DCHECK(visible_);
commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; needs_commit_ = false;
last_frame_number_begin_main_frame_sent_ = current_frame_number_; return;
case ACTION_COMMIT: {
bool commit_was_aborted = false;
UpdateStateOnCommit(commit_was_aborted); return; }
case ACTION_DRAW_AND_SWAP_FORCED:
case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { bool did_request_swap = true;
UpdateStateOnDraw(did_request_swap); return; }
case ACTION_DRAW_AND_SWAP_ABORT: { bool did_request_swap = false;
UpdateStateOnDraw(did_request_swap); return; }
case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); output_surface_state_ = OUTPUT_SURFACE_CREATING;
// The following DCHECKs make sure we are in the proper quiescent state. // The pipeline should be flushed entirely before we start output // surface creation to avoid complicated corner cases.
DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); DCHECK(!has_pending_tree_);
DCHECK(!active_tree_needs_first_draw_);