分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
Android WebView作为App UI的一部分,当App UI以硬件加速方式渲染时,它也是以硬件加速方式渲染的。Android WebView的UI来自于网页,是通过Chromium渲染的。Chromium渲染网页UI的机制与Android App渲染UI的机制是不一样的。不过,它们会一起协作完成网页UI的渲染。本文接下来就详细分析Android WebView硬件加速渲染网页UI的过程。
老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!
《Android系统源代码情景分析》一书正在进击的程序员网(http://0xcc0xcd.com)中连载,点击进入!
从前面Android应用程序UI硬件加速渲染技术简要介绍和学习计划这个系列的文章可以知道,Android App在渲染UI一帧的过程中,经历以下三个阶段:
1. 在UI线程中构建一个Display List,这个Display List包含了每一个View的绘制命令。
2. 将前面构建的Display List同步给Render Thread。
3. Render Thread对同步得到的Display List进行渲染,也就是使用GPU执行Display List的绘制命令。
上述三个阶段如果能够在16ms内完成,那么App的UI给用户的感受就是流畅的。为了尽量地在16ms内渲染完成App的一帧UI,Android使用了以上方式对App的UI进行渲染。这种渲染机制的好处是UI线程和Render Thread可以并发执行,也就是Render Thread在渲染当前帧的Display List的时候,UI线程可以准备下一帧的Display List。它们唯一需要同步的地方发生第二阶段。不过,这个阶段是可以很快完成的。因此,UI线程和Render Thread可以认为是并发执行的。
Android WebView既然是App UI的一部分,也就是其中的一个View,它的渲染也是按照上述三个阶段进行的,如下所示:
图1 Android WebView硬件加速渲染网页UI的过程
在第一阶段,Android WebView会对Render端的CC Layer Tree进行绘制。这个CC Layer Tree描述的就是网页的UI,它会通过一个Synchronous Compositor绘制在一个Synchronous Compositor Output Surface上,最终得到一个Compositor Frame。这个Compositor Frame会保存在一个SharedRendererState对象中。
在第二阶段,保存在上述SharedRendererState对象中的Compositor Frame会同步给Android WebView会对Browser端的CC Layer Tree。Browser端的CC Layer Tree只有两个节点。一个是根节点,另一个是根节点的子节点,称为一个Delegated Renderer Layer。Render端绘制出来的Compositor Frame就是作为这个Delegated Renderer Layer的输入的。
在第三阶段,Android WebView会通过一个Hardware Renderer将Browser端的CC Layer Tree渲染在一个Parent Output Surface上,实际上就是通过GPU命令将Render端绘制出来的UI合成显示在App的UI窗口中。
接下来,我们就按照以上三个阶段分析Android WebView硬件加速渲染网页UI的过程。
从前面Android应用程序UI硬件加速渲染的Display List构建过程分析一文可以知道,在App渲染UI的第一阶段,Android WebView的成员函数onDraw会被调用。从前面Android WebView执行GPU命令的过程分析一文又可以知道,Android WebView在Native层有一个BrowserViewRenderer对象。当Android WebView的成员函数onDraw被调用时,并且App的UI以硬件加速方式渲染时,这个Native层BrowserViewRenderer对象的成员函数OnDrawHardware会被调用,如下所示:
bool BrowserViewRenderer::OnDrawHardware(jobject java_canvas) { ...... scoped_ptr<DrawGLInput> draw_gl_input(new DrawGLInput); ...... scoped_ptr<cc::CompositorFrame> frame = compositor_->DemandDrawHw(surface_size, gfx::Transform(), viewport, clip, viewport_rect_for_tile_priority, transform_for_tile_priority); ...... frame->AssignTo(&draw_gl_input->frame); ...... shared_renderer_state_->SetDrawGLInput(draw_gl_input.Pass()); ...... return client_->RequestDrawGL(java_canvas, false); }
这个函数定义在文件external/chromium_org/android_webview/browser/browser_view_renderer.cc中。
从前面Android WebView执行GPU命令的过程分析一文可以知道,BrowserViewRenderer类的成员变量compositor_指向的是一个SynchronousCompositorImpl对象。BrowserViewRenderer对象的成员函数OnDrawHardware会调用这个SynchronousCompositorImpl对象的成员函数DemandDrawHw对网页的UI进行绘制。
绘制的结果是得到一个Compositor Frame。这个Compositor Frame会保存在一个DrawGLInput对象中。这个DrawGLInput对象又会保存在BrowserViewRenderer类的成员变量shared_renderer_state_指向的一个SharedRendererState对象中。这是通过调用SharedRendererState类的成员函数SetDrawGLInput实现的。
BrowserViewRenderer类的成员变量client_指向的是一个AwContents对象。BrowserViewRenderer对象的成员函数OnDrawHardware最后会调用这个AwContents对象的成员函数RequestDrawGL请求在参数java_canvas描述的一个Hardware Canvas中增加一个DrawFunctorOp操作。这个DrawFunctorOp操作最终会包含在App的UI线程构建的Display List中。
接下来,我们首先分析SynchronousCompositorImpl类的成员函数DemandDrawHw绘制网页的UI的过程,如下所示:
scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw( gfx::Size surface_size, const gfx::Transform& transform, gfx::Rect viewport, gfx::Rect clip, gfx::Rect viewport_rect_for_tile_priority, const gfx::Transform& transform_for_tile_priority) { ...... scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawHw(surface_size, transform, viewport, clip, viewport_rect_for_tile_priority, transform_for_tile_priority); ...... return frame.Pass();}
这个函数定义在文件external/chromium_org/content/browser/android/in_process/synchronous_compositor_impl.cc中。