网页绘图表面最初处于OUTPUT_SURFACE_LOST状态,等到CC Layer Tree创建之后,调度器会调度图2所示的第2个操作ACTION_BEGIN_OUTPUT_SURFACE_CREATION,也就是请求Compositor线程为网页创建绘图表面,这时候网页绘图表面的状态变为OUTPUT_SURFACE_CREATING。
Compositor线程为网页创建好了绘图表面之后,就会调用SchedulerStateMachine类的成员函数DidCreateAndInitializeOutputSurface将绘图表面的状态设置为OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT。这将会触发调度器尽快调度执行图2所示的第2个操作ACTION_SEND_BEGIN_MAIN_FRAME和第3个操作ACTION_COMMIT,也就是请求Main线程对CC Layer Tree进行绘制,并且将其同步到CC Pending Layer Tree中去。这时候绘图表面的状态变为OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,表示要尽快将CC Pending Layer Tree激活为CC Active Layer Tree。
CC Pending Layer Tree被激活之后,也就是图2所示的第5个操作ACTION_ACTIVATE_PENDING_TREE执行之后,绘图表面以后就会一直处于OUTPUT_SURFACE_ACTIVE状态。不过,在绘图表面处于OUTPUT_SURFACE_ACTIVE状态期间,如果Render进程与GPU进程之间的GPU通道断开了连接,或者GPU进程在解析Render进程发送来的GPU命令时发生了错误,那么SchedulerStateMachine类的成员函数DidLoseOutputSurface会被调用。这时候绘图表面的状态就会被设置为OUTPUT_SURFACE_LOST状态。这将会触发调度器调度执行ACTION_BEGIN_OUTPUT_SURFACE_CREATION操作,以便为网页重新创建绘图表面。
CommitState描述的是CC Layer Tree的提交状态,包括同步到CC Pending Layer Tree,以及CC Pending Layer Tree激活为CC Active Layer Tree的过程,如下所示:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 class CC_EXPORT SchedulerStateMachine { public: ......
enum CommitState {
COMMIT_STATE_IDLE,
COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED, COMMIT_STATE_READY_TO_COMMIT,
COMMIT_STATE_WAITING_FOR_ACTIVATION, COMMIT_STATE_WAITING_FOR_FIRST_DRAW, };
......
private: ......
CommitState commit_state_; ...... };
这个状态定义在文件external/chromium_org/cc/scheduler/scheduler_state_machine.h中。 CC Layer Tree的提交状态记录在SchedulerStateMachine类的成员变量commit_state_中。CC Layer Tree有六个提交状态,分别是:
1. COMMIT_STATE_IDLE
2. COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
3. COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED
4. COMMIT_STATE_READY_TO_COMMIT
5. COMMIT_STATE_WAITING_FOR_ACTIVATION
6. COMMIT_STATE_WAITING_FOR_FIRST_DRAW
它们的变迁关系如图5所示:
CC Layer Tree的提交状态最开始时被设置为COMMIT_STATE_IDLE。当调度器调度执行图2所示的第2个操作ACTION_BEGIN_MAIN_FRAME时,CC Layer Tree的提交状态被设置为COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,表示调度器已经请求Main线程对CC Layer Tree进行绘制。
在Main线程执行ACTION_BEGIN_MAIN_FRAME操作期间,CC Layer Tree有可能变为不可见,这时候调度器就会调用SchedulerStateMachine类的成员函数BeginMainFrameAborted重新设置为COMMIT_STATE_IDLE。
Main线程执行完成ACTION_BEGIN_MAIN_FRAME操作之后,调度器就会调用SchedulerStateMachine类的成员函数NotifyReadyToCommit将CC Layer Tree的提交状态设置为COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED。这时候Main线程会通知Compositor线程对网页中的图片资源以纹理方式上传到GPU去,以便后面进行渲染显示。
图片资源上传完毕,调度器就会调用SchedulerStateMachine类的成员函数NotifyReadyToCommit将CC Layer Tree的提交状态设置为COMMIT_STATE_READY_TO_COMMIT,表示CC Layer Tree需要同步到CC Pending Layer Tree中去。这将会触发调度器调度执行图2所示的第三个操作ACTION_COMMIT,也就是将CC Layer Tree同步到CC Pending Layer Tree中去。
ACTION_COMMIT操作执行完成之后,CC Layer Tree的提交状态会从COMMIT_STATE_READY_TO_COMMIT变为以下三个状态之一:
1. 在满足以下两个条件之一时,变为COMMIT_STATE_IDLE:
A. main_frame_before_activation_enabled被设置为true。这表示在上一个CC Pending Layer Tree被激活为CC Active Layer Tree之前,允许Main线程绘制网页的下一帧。
B. main_frame_before_draw_enabled被设置为true,但是impl_side_painting被设置为false。main_frame_before_draw_enabled设置为true,表示在上一个CC Active Layer Tree被渲染之前,允许Main线程绘制网页的下一帧。impl_side_painting设置为true表示Main线程在绘制网页时,实际上只是记录了网页的绘制命令。只有在impl_side_painting设置为true的时候,才会有CC Pending Layer Tree被激活为CC Active Layer Tree的环节。因此,在impl_side_painting等于false的情况下,main_frame_before_draw_enabled被设置为true等同于main_frame_before_activation_enabled被设置为true的情况。
2. FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION。需要满足的条件是main_frame_before_draw_enabled和impl_side_painting均被设置为true,并且main_frame_before_activation_enabled被设置为false。这表示在上一个CC Pending Layer Tree被激活为CC Active Layer Tree之后,才允许Main线程绘制网页的下一帧。
3. COMMIT_STATE_WAITING_FOR_FIRST_DRAW。需要满足的条件是main_frame_before_activation_enabled和main_frame_before_draw_enabled均被设置为true。这表示在上一个CC Active Layer Tree第一次渲染之后,才允许Main线程绘制网页的下一帧。这实际上是给予CC Active Layer Tree更高的优先级,使得它一激活就马上进行渲染。
如果CC Layer Tree的提交状态处于FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,那么当CC Pending Layer Tree被激活为CC Active Layer Tree之后,也就是图2所示的第5个操作ACTION_ACTIVATE_PENDING_TREE执行之后,CC Layer Tree的提交状态就变为COMMIT_STATE_IDLE。
如果CC Layer Tree的提交状态处于COMMIT_STATE_WAITING_FOR_FIRST_DRAW,那么当CC Active Layer Tree被渲染之后,也就是图2所示的第6个操作ACTION_DRAW_AND_SWAP_FORCED,或者另外一个操作ACTION_DRAW_AND_SWAP_IF_POSSIBLE执行之后,CC Layer Tree的提交状态就变为COMMIT_STATE_IDLE。
注意,只有CC Layer Tree的提交状态处于COMMIT_STATE_IDLE时,Main线程才可以绘制网页的下一帧。
ForcedRedrawOnTimeoutState描述的是网页的渲染状态,如下所示:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 class CC_EXPORT SchedulerStateMachine { public: ......
enum ForcedRedrawOnTimeoutState { FORCED_REDRAW_STATE_IDLE,
FORCED_REDRAW_STATE_WAITING_FOR_COMMIT, FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,
FORCED_REDRAW_STATE_WAITING_FOR_DRAW, };
......
private: ......
ForcedRedrawOnTimeoutState forced_redraw_state_; ...... };
这个状态定义在文件external/chromium_org/cc/scheduler/scheduler_state_machine.h中。
网页的渲染状态记录在SchedulerStateMachine类的成员变量forced_redraw_state_中。网页的渲染状态有四个,分别是:
1. FORCED_REDRAW_STATE_IDLE,
2. FORCED_REDRAW_STATE_WAITING_FOR_COMMIT
3. FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
4. FORCED_REDRAW_STATE_WAITING_FOR_DRAW
它们的变迁关系如图6所示:
网页渲染状态最开始处于FORCED_REDRAW_STATE_IDLE状态。在渲染动画的过程中,如果某些分块(Tile)还没有光栅化好,那么CC模块就会用棋盘(Checkboard)来代替这些缺失的分块。这时候的网页渲染结果被视为DRAW_ABORTED_CHECKERBOARD_ANIMATIONS。如果网页连续渲染结果都是DRAW_ABORTED_CHECKERBOARD_ANIMATIONS的次数超出预设值,那么网页渲染状态就会被设置为FORCED_REDRAW_STATE_WAITING_FOR_COMMIT,表示要尽快执行