chromium:LoadUrl之后会发生那些事情之OnDraw

本文深入分析了Chromium WebView的渲染架构,特别是M42内核中的SynchronousCompositor和ParentCompositor。在UI线程,SynchronousCompositor处理绘制需求,而在渲染线程,ParentCompositor完成合成。硬件渲染过程中,通过SharedRendererState进行跨线程同步,最终在Renderer线程完成DrawGL操作。

一 综述

自从Android系统WebView内核使用chromium以来,其渲染机制一直在持续不断演进,本文将以M42内核分析WebView的渲染架构以及相关代码分析。

先从代码流程进行分析,当WebView需要重新绘制时会调用

WebView.OnDraw(Canvas canvas)

--->WebViewChromium.onDraw(Canvas canvas)

-->AwContents.onDraw(Canvas canvas)

AwContents中,通过native方法(nativewOnDraw)继续进入C++层,AwContents::OnDraw(),在这里会决定是软件渲染,还是硬件渲染。当硬件渲染时,调用

BrowserViewRenderer::OnDrawHardware()

在代码中,我们看到BrowserViewRenderer的解释是Interface for all the WebView-specific content rendering operations.,可知它是专门为Android WebView渲染机制而生的。

这里继续分析发现最新的Chromium WebView渲染机制采用了两级合成器,分别是SynchronousCompositorParentCompositor,它们分别运行在UI线程和Renderer线程,

通过SharedRendererState进行跨线程数据同步和共享。

二 SynchronousCompositor

WebView发生任何需要绘制时,这是在UI线程,它会走到同步合成器:SynchronousCompositor

SynchronousCompositor是虚基类,它的实现类对象是SynchronousCompositorImp通过DidInitializeCompositor()直接将其传到BrowserViewRenderer中。

当需要硬件渲染时,在BrowserViewRenderer::OnDrawHardware()

会调用BrowserViewRenderer::CompositeHw()

--->SynchronousCompositorImp::DemandDrawHw()

--->SynchronousCompositorOutputSurface::DemandDrawHw()

--->SynchronousCompositorOutputSurface::InvokeComposite()

---->SynchronousCompositorExternalBeginFrameSource::BeginFrame()

接着就到达cc中的ThreadProxy::BeginMainFrame(), 然后就如之前 五、六、七、八四篇中所述那样进行网页重新Layout, UpdateLayersDrawLayers,最后将收集好的所有绘制命令PrepareSendToParent()

三 ParentCompositor

前面的SynchronousCompositor,相对于ParentCompositor也可以叫child compositorParentCompositor是在HardwareRenderer中创建的, 它也有相应的OutputSurface,叫

ParentOutputSurface

来看看渲染线程的compositor,在HardwareRenderer中,首先会创建root_layer_layer_tree_host_output_surface_以及SingleThreadProxy,另外,root_layer_的子树是一个DelegatedRendererLayer,有且只有一个子树,由此可见这颗Tree是非常简单的。这样就构成了完整的渲染线程合成器。

四 绘制

UI线程,BrowserViewRenderer::OnDrawHardware()得到网页的合成结果CompositeFrame后,调用shared_renderer_state_.SetCompositorFrameOnUI(frame.Pass(), false);

CompositeFrame传给SharedRendererState,以便渲染线程的合成器使用。

Renderer线程,HardwareRenderer::DrawGL()首先会

#1  调用HardwareRenderer::CommitFrame(),将UI线程中保存在SharedRendererState中的CompositeFrame同步过来,即

committed_frame_ = shared_renderer_state_->PassCompositorFrameOnRT();

#2 调用HardwareRenderer::SetFrameData(),将committed_frame_传给合成器,代码如下:

171 void HardwareRenderer::SetFrameData() {

172   if (!committed_frame_.get())

173     return;

174 

175   scoped_ptr<cc::CompositorFrame> frame = committed_frame_.Pass();

176   gfx::Size frame_size =

177       frame->delegated_frame_data->render_pass_list.back()->output_rect.size();

178   bool size_changed = frame_size != frame_size_;

179   frame_size_ = frame_size;

180 

181   if (!frame_provider_.get() || size_changed) {

182     if (delegated_layer_.get()) {

183       delegated_layer_->RemoveFromParent();

184     }

185 

186     frame_provider_ = new cc::DelegatedFrameProvider(

187         resource_collection_.get(), frame->delegated_frame_data.Pass());                                                                                                            

188 

189     delegated_layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);

190     delegated_layer_->SetBounds(frame_size_);

191     delegated_layer_->SetIsDrawable(true);

192 

193     root_layer_->AddChild(delegated_layer_);

194   } else {

195     frame_provider_->SetFrameData(frame->delegated_frame_data.Pass());

196   }

197 }

 

#3 绑定当前FBO,合成器进行合成操作,代码如下:

246   gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext);                                                                                                                

247   {

248     base::AutoReset<bool> frame_resetter(&viewport_clip_valid_for_dcheck_,

249                                          true);

250     layer_tree_host_->SetNeedsRedrawRect(clip_);

251     layer_tree_host_->Composite(gfx::FrameTime::Now());

252   }

253   gl_surface_->ResetBackingFrameBufferObject();

254 }

 

#4 composite合成操作流程

LayerTreeHost::Composite()

-->SingleThreadProxy::CompositeImmediately()

--->SingleThreadProxy::DoComposite()

---->LayerTreeHostImpl::DrawLayers()

---->GLRenderer::DrawFrame()

---->DirectRenderer::DrawFrame()

---->DirectRenderer::DrawRenderPass()

---->GLRenderer::DoDrawQuad()

五 总结

硬件渲染逻辑分解为两个步骤:

#1 UI线程上调用Synchronous Compositor合成操作生成新的CompositorFrame,再向Android系统请求执行DrawGL回调函数,但此时DrawGL并不会立即执行。

UI线程负责为发生invalidate操作的View生成显示列表,再将这个显示列表同步给渲染线程上的HardwareRenderer;

#2 Android View系统在渲染线程上将显示列表提交给GPU驱动,绘制View层次的内容,在绘制显示列表的过程中,DrawGL函数将会被调用,在渲染线程上请求

Parent Compositor将合成的页面内容绘制到HardwareCanvas上。

上述整个过程可以用下图来表示。

 

Android WebView渲染流程图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值