您的位置:首页 > 其它

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

2015-07-25 16:37 369 查看
一 综述

自从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渲染机制采用了两级合成器,分别是SynchronousCompositor和ParentCompositor,它们分别运行在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, UpdateLayers,DrawLayers,最后将收集好的所有绘制命令PrepareSendToParent()。

三 ParentCompositor

前面的SynchronousCompositor,相对于ParentCompositor也可以叫child compositor。ParentCompositor是在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渲染流程图
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: