




已阅读5页,还剩42页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Chromium网页渲染调度器(Scheduler)实现分析在采用线程化渲染方式渲染网页时,Chromium依赖一个调度器协调Main线程和Compositor线程的执行,同时也通过这个调度器决定它们什么时候该执行什么操作。调度器将Main线程和Compositor线程的当前状态记录在一个状态机中,然后通过这个状态机决定下一个要执行的操作。这个操作在满足当前设置条件下是最优的,因此可以使网页渲染更快更流畅。本文接下来就分析Chromium网页调度器的实现。调度器实现在Chromium的CC模块中,并且运行在Compositor线程中。Compositor线程的职责是将网页的内容渲染出来。从这个角度看,调度器只不过是在调度Compositor线程的执行。不过由于要渲染的网页内容是由Main线程提供给Compositor线程的,因此调度器也会在必要的时候调度Main线程执行,使得它可以提供最新的网页内容给Compositor线程渲染。 网页是一帧一帧地渲染出来的。从前面这个系列的文章我们学习到,Android应用程序UI的每一帧的最佳渲染时机是下一个屏幕VSync信号到来时。Chromium也不例外,它在渲染网页的时候,也是利用了屏幕的VSync信号。这一点在调度器的时间轴中可以得到体现,如图1所示:从图1可以看到,调度器并没有严格在VSync到来时就去渲染网页的下一帧,而是为网页的下一帧渲染时机设置了一个Deadline。在Deadline到来前,调度器可以调度执行其它的渲染操作。 在继续分析上述的Deadline机制之前,我们要先搞清楚网页的一帧渲染涉及到哪些操作。这些操作如图2所示:图2的完整分析可以参考前面一文。我们前面说的Deadline,是针对第6个操作ACTION_DRAW_AND_SWAP_FORCED而言的。也就是说,当VSync信号到来时,ACTION_DRAW_AND_SWAP_FORCED操作最迟必须在设置的Deadline到来时执行。 这个Deadline是怎么计算出来的呢?我们先来看网页的渲染过程。首先是Render进程进行渲染,然后交给Browser进程进行合成。因此,网页的渲染过程可以看作由两部分时间组成:estimated_draw_duration + estimated_browser_composite_time。其中,estimated_draw_duration表示Render进程的渲染时间,estimated_browser_composite_time表示Browser进程的合成时间。 假设下一个VSync到来的时间为frame_time,VSync信号时间周期为interval,那么就可以计算出Deadline = frame_time + (interval - estimated_draw_duration - estimated_browser_composite_time)。剩下来的时间区间frame_time, deadline)可以用做其它事情,例如执行图2所示的第2个操作ACTION_SEND_BEGIN_MAIN_FRAME,也就是通知Main线程对CC Layer Tree进行绘制。 时间区间frame_time, deadline)称为BEGIN_IMPL_FRAME时间。在BEGIN_IMPL_FRAME时间内,存在四个BeginImplFrameState状态,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片class CC_EXPORT SchedulerStateMachine public: . / Note: BeginImplFrameState will always cycle through all the states in / order. Whether or not it actually waits or draws, it will at least try to / wait in BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in / BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE enum BeginImplFrameState BEGIN_IMPL_FRAME_STATE_IDLE, BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, ; . protected: . BeginImplFrameState begin_impl_frame_state_; . ; 这个状态定义在文件external/chromium_org/cc/scheduler/scheduler_state_machine.h中。 调度器通过类SchedulerStateMachine描述内部的状态机。状态机的BeginImplFrameState状态记录在SchedulerStateMachine类的成员变量begin_impl_frame_state_中。 四个BeginImplFrameState状态分别为: 1. BEGIN_IMPL_FRAME_STATE_IDLE 2. BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING 3. BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME 4. BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE 它们的变迁关系如图3所示:下一个VSync信号到来之前,状态机处于BEGIN_IMPL_FRAME_STATE_IDLE状态。 下一个VSync信号到来之时,调度器调用SchedulerStateMachine类的成员函数OnBeginImplFrame将状态机的BeginImplFrameState状态设置为BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING。这时候调度器通过调用Scheduler类的成员函数ProcessScheduledActions调度计算网页中的动画,或者执行图2所示的第2个操作ACTION_SEND_BEGIN_MAIN_FRAME,也就是通知Main线程对网页内容进行绘制。 从Scheduler类的成员函数ProcessScheduledActions返回后,BeginImplFrameState状态就从BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING变为BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME。这时候调度器等待Deadline的到来。 Deadline到来之时,调度器调用SchedulerStateMachine类的成员函数OnBeginImplFrameDeadline将BeginImplFrameState状态从BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME设置为BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE。这时候调度器就会通过调用Scheduler类的成员函数ProcessScheduledActions调度执行网页的渲染操作,也就是图2所示的第6个操作ACTION_DRAW_AND_SWAP_FORCED。 从Scheduler类的成员函数ProcessScheduledActions返回后,BeginImplFrameState状态就从BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE重新变为BEGIN_IMPL_FRAME_STATE_IDLE。这时候调度器等待再下一个VSync信号的到来。 状态机除了有BeginImplFrameState状态,还有其它三个状态,分别是OutputSurfaceState、CommitState和ForcedRedrawOnTimeoutState。 OutputSurfaceState描述的是网页绘图表面的状态,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片class CC_EXPORT SchedulerStateMachine public: . enum OutputSurfaceState OUTPUT_SURFACE_ACTIVE, OUTPUT_SURFACE_LOST, OUTPUT_SURFACE_CREATING, OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT, OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION, ; . protected: . OutputSurfaceState output_surface_state_; . ; 这个状态定义在文件external/chromium_org/cc/scheduler/scheduler_state_machine.h中。 网页绘图表面的状态记录在SchedulerStateMachine类的成员变量output_surface_state_中。网页绘图表面的状态有五个状态,分别是: 1. OUTPUT_SURFACE_LOST 2. OUTPUT_SURFACE_CREATING 3. OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT 4. OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION 5. OUTPUT_SURFACE_ACTIVE 它们的变迁关系如图4所示:网页绘图表面最初处于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,表示要尽快执行一次图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 mark_inside_action(&inside_action_, action); switch (action) 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 = fa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 建筑装饰工程技术创新应用方案
- 智能建筑楼层空调系统方案
- 小学数学学科实践的内涵、特征及样态
- 全国中学生物理竞赛实验试题及答案
- 人力资源知识竞赛试题及答案 HR
- 社会工作者考试模拟试题及答案
- 2025殡葬考试真题及答案
- 村级财务管理培训试题及答案
- 本地仓储生产计划考试题
- 有限空间安全考试题
- 2025年全国保密教育线上培训考试试题库附答案【考试直接用】含答案详解
- 2025年度全国普通话水平测试20套复习题库及答案
- 2025年初级会计师考试真题试题及答案
- 上海嘉定区区属国有企业招聘考试真题2024
- 2025心肺复苏术课件
- T-CECS 10400-2024 固废基胶凝材料
- 2025年内蒙古三新铁路有限责任公司招聘笔试参考题库含答案解析
- 初中竞选安全部部长
- 《人体的经络》课件
- 《福禄贝尔》课件
- 期中测试卷(第一单元至第四单元)-2024-2025学年六年级上册数学人教版
评论
0/150
提交评论