1、Chromium网页Layer Tree创建过程分析Chromium网页Layer Tree创建过程分析在Chromium中,WebKit会创建一个Graphics Layer Tree描述网页。Graphics Layer Tree是和网页渲染相关的一个Tree。网页渲染最终由Chromium的CC模块完成,因此CC模块又会根据Graphics Layer Tree创建一个Layer Tree,以后就会根据这个Layer Tree对网页进行渲染。本文接下来就分析网页Layer Tree的创建过程。从前面一文可以知道,网页的Graphics Layer Tree是根据Render Layer
2、Tree创建的,Render Layer Tree又是根据Render Object Tree创建的。Graphics Layer Tree与Render Layer Tree、Render Layer Tree与Render Object Tree的节点是均是一对多的关系,然而Graphics Layer Tree与CC模块创建的Layer Tree的节点是一一对应的关系,如图1所示:也就是说,每一个Graphics Layer都对应有一个CC Layer。不过,Graphics Layer与CC Layer不是直接的一一对应的,它们是透过另外两个Layer才对应起来的,如图2所示: 中间的
3、两个Layer分别是WebContentLayerImpl和WebLayerImpl,它们是属于Content层的对象。关于Chromium的层次划分,可以参考前面一文的介绍。Graphics Layer与CC Layer的对应关系,是在Graphics Layer的创建过程中建立起来的,接下来我们就通过源码分析这种对应关系的建立过程。 从前面一文可以知道,Graphics Layer是通过调用GraphicsLayerFactoryChromium类的成员函数createGraphicsLayer创建的,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片
4、PassOwnPtr GraphicsLayerFactoryChromium:createGraphicsLayer(GraphicsLayerClient* client) OwnPtr layer = adoptPtr(new GraphicsLayer(client); . return layer.release(); 这个函数定义在文件external/chromium_org/third_party/WebKit/Source/web/GraphicsLayerFactoryChromium.cpp中。 参数client指向的实际上是一个CompositedLayerMappin
5、g对象,这个CompositedLayerMapping对象会用来构造一个Graphics Layer。Graphics Layer的构造过程,也就是GraphicsLayer类的构造函数的实现,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片GraphicsLayer:GraphicsLayer(GraphicsLayerClient* client) : m_client(client) , . . m_opaqueRectTrackingContentLayerDelegate = adoptPtr(new OpaqueRectTrackingCo
6、ntentLayerDelegate(this); m_layer = adoptPtr(Platform:current()-compositorSupport()-createContentLayer(m_opaqueRectTrackingContentLayerDelegate.get(); . 这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。 GraphicsLayer类的构造函数首先是将参数client指向的CompositedLayerMap
7、ping对象保存在成员变量m_client中,接着又创建了一个OpaqueRectTrackingContentLayerDelegate对象保存在成员变量opaqueRectTrackingContentLayerDelegate中。 再接下来GraphicsLayer类的构造函数通过Platform类的静态成员函数current获得一个RendererWebKitPlatformSupportImpl对象。这个RendererWebKitPlatformSupportImpl对象定义在Content模块中,它实现了由WebKit定义的Platform接口,用来向WebKit层提供平台相关的
8、实现。 通过调用RendererWebKitPlatformSupportImpl类的成员函数compositorSupport可以获得一个WebCompositorSupportImpl对象。有了这个WebCompositorSupportImpl对象之后,就可以调用它的成员函数createContentLayer创建一个WebContentLayerImpl对象,并且保存在GraphicsLayer类的成员变量m_layer中。 WebCompositorSupportImpl类的成员函数createContentLayer的实现如下所示:cpp view plain copy 在CODE
9、上查看代码片派生到我的代码片WebContentLayer* WebCompositorSupportImpl:createContentLayer( WebContentLayerClient* client) return new WebContentLayerImpl(client); 这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_compositor_support_impl.cc中。 从这里可以看到,WebCompositorSupportImpl类的成员函数createContentL
10、ayer创建了一个WebContentLayerImpl对象返回给调用者。 WebContentLayerImpl对象的创建过程,即WebContentLayerImpl类的构造函数的实现,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片WebContentLayerImpl:WebContentLayerImpl(blink:WebContentLayerClient* client) : client_(client), . if (WebLayerImpl:UsingPictureLayer() layer_ = make_scoped_ptr(n
11、ew WebLayerImpl(PictureLayer:Create(this); else layer_ = make_scoped_ptr(new WebLayerImpl(ContentLayer:Create(this); . 这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_content_layer_impl.cc中。 从前面的调用过程可以知道,参数client指向的实际上是一个OpaqueRectTrackingContentLayerDelegate对象,WebContentLaye
12、rImpl类的构造函数首先将它保存在成员变量client_中 。 WebContentLayerImpl类的构造函数接下来调用WebLayerImpl类的静态成员函数UsingPictureLayer判断Render进程是否启用Impl Side Painting特性。如果启用的话,就会调用PictureLayer类的静态成员函数Create创建一个Picture Layer;否则的话,就会调用ContentLayer类的静态成员函数Create创建一个Content Layer。有了Picture Layer或者Content Layer之后,再创建一个WebLayerImpl对象,保存在W
13、ebContentLayerImpl类的成员变量layer_中。 当Render进程设置了enable-impl-side-painting启动选项时,就会启用Impl Side Painting特性,也就是会在Render进程中创建一个Compositor线程,与Render进程中的Main线程一起协作完成网页的渲染。在这种情况下,Graphics Layer在绘制网页内容的时候,实际上只是记录了绘制命令。这些绘制命令就记录在对应的Picture Layer中。 另一方面,如果Render进程没有设置enable-impl-side-painting启动选项,那么Graphics Layer
14、在绘制网页内容的时候,就会通过Content Layer提供的一个Canvas真正地把网页内容对应的UI绘制在一个内存缓冲区中。 无论是Picture Layer还是Content Layer,它们都是在cc:Layer类继承下来的,也就是说,它们对应于图2所示的CC Layer。不过,我们只考虑Picture Layer的情况,因此接下来我们继续分析Picture Layer的创建过程,也就是PictureLayer类的静态成员函数Create的实现,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片scoped_refptr PictureLayer:
15、Create(ContentLayerClient* client) return make_scoped_refptr(new PictureLayer(client); 这个函数定义在文件external/chromium_org/cc/layers/picture_layer.cc中。 从这里可以看到,PictureLayer类的静态成员函数Create创建了一个PictureLayer对象返回给调用者。 PictureLayer对象的创建过程,也就是PictureLayer类的构造函数的实现,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片Pic
16、tureLayer:PictureLayer(ContentLayerClient* client) : client_(client), pile_(make_scoped_refptr(new PicturePile(), . 这个函数定义在文件external/chromium_org/cc/layers/picture_layer.cc中。 从前面的调用过程可以知道,参数client指向的实际上是一个WebContentLayerImpl对象,PictureLayer类的构造函数将它保存在成员变量client_中。 PictureLayer类的构造函数还做了另外一件重要的事情,就是创建
17、了一个PicturePile对象,并且保存在成员变量pile_中。这个PicturePile对象是用来将Graphics Layer的绘制命令记录在Pictrue Layer中的,后面我们分析网页内容的绘制过程时就会看到这一点。 回到WebContentLayerImpl类的构造函数中,它创建了一个Pictrue Layer之后,接下来就会以这个Pictrue Layer为参数,创建一个WebLayerImpl对象,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片WebLayerImpl:WebLayerImpl(scoped_refptr layer)
18、 : layer_(layer) . 这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_layer_impl.cc中。 WebLayerImpl类的构造函数主要就是将参数layer描述的一个PictrueLayer对象保存在成员变量layer_中。 从前面一文还可以知道,Graphics Layer与Graphics Layer是通过GraphicsLayer类的成员函数addChild形成父子关系的(从而形成Graphics Layer Tree),如下所示:cpp view plain copy
19、在CODE上查看代码片派生到我的代码片void GraphicsLayer:addChild(GraphicsLayer* childLayer) addChildInternal(childLayer); updateChildList(); 这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。 GraphicsLayer类的成员函数addChild首先调用成员函数addChildInternal将参数childLayer描述的一个Graphics Laye
20、r作为当前正在处理的Graphics Layer的子Graphics Layer,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void GraphicsLayer:addChildInternal(GraphicsLayer* childLayer) . childLayer-setParent(this); m_children.append(childLayer); . 这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.
21、cpp中。 这一步执行完成后,Graphics Layer之间就建立了父子关系。回到GraphicsLayer类的成员函数addChild中,它接下来还会调用另外一个成员函数updateChildList,用来在CC Layer之间建立父子关系,从而形CC Layer Tree。 GraphicsLayer类的成员函数updateChildList的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void GraphicsLayer:updateChildList() WebLayer* childHost = m_layer-layer(); .
22、for (size_t i = 0; i addChild(m_childreni-platformLayer(); . 这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。 从前面的分析可以知道,GraphicsLayer类的成员变量m_layer指向的是一个WebContentLayerImpl对象,调用这个WebContentLayerImpl对象的成员函数layer获得的是一个WebLayerImpl对象,如下所示:cpp view plain cop
23、y 在CODE上查看代码片派生到我的代码片blink:WebLayer* WebContentLayerImpl:layer() return layer_.get(); 这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_content_layer_impl.cc中。 从前面的分析可以知道,WebContentLayerImpl类的成员变量layer_指向的是一个WebLayerImpl对象,因此WebContentLayerImpl类的成员函数layer返回的是一个WebLayerImpl对象。 回
24、到GraphicsLayer类的成员函数updateChildList中,它接下来调用GraphicsLayer类的成员函数platformLayer获得当前正在处理的Graphics Layer的所有子Graphics Layer对应的WebLayerImpl对象,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片WebLayer* GraphicsLayer:platformLayer() const return m_layer-layer(); 这个函数定义在文件external/chromium_org/third_party/WebKit/So
25、urce/platform/graphics/GraphicsLayer.cpp中。 这些子Graphics Layer对应的WebLayerImpl对象也就是通过调用它们的成员变量m_layer指向的WebContentLayerImpl对象的成员函数layer获得的。 再回到GraphicsLayer类的成员函数updateChildList中,获得当前正在处理的Graphics Layer对应的WebLayerImpl对象,以及其所有的子Graphics Layer对应的WebLayerImpl对象之后,就可以通过调用WebLayerImpl类的成员函数addChild在它们之间也建立父
26、子关系,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void WebLayerImpl:addChild(WebLayer* child) layer_-AddChild(static_cast(child)-layer(); 这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_layer_impl.cc中。 从前面的分析可以知道,WebLayerImpl类的成员变量layer_指向的是一个PictrueLayer对象,因此WebLayerImpl类的成员函数
27、addChild所做的事情就是在两个PictrueLayer对象之间建立父子关系,这是通过调用PictrueLayer类的成员函数AddChild实现的。 PictrueLayer类的成员函数AddChild是父类Layer继承下来的,它的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void Layer:AddChild(scoped_refptr child) InsertChild(child, children_.size(); 这个函数定义在文件external/chromium_org/cc/layers/layer.cc中。 Laye
28、r类的成员函数AddChild将参数child描述的Pictrue Layer设置为当前正在处理的Picture Layer的子Picture Layer,这是通过调用Layer类的成员函数InsertChild实现的,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void Layer:InsertChild(scoped_refptr child, size_t index) DCHECK(IsPropertyChangeAllowed(); child-RemoveFromParent(); child-SetParent(this); child
29、-stacking_order_changed_ = true; index = std:min(index, children_.size(); children_.insert(children_.begin() + index, child); SetNeedsFullTreeSync(); 这个函数定义在文件external/chromium_org/cc/layers/layer.cc中。 Layer类的成员函数InsertChild所做的第一件事情是将当前正在处理的Picture Layer设置为参数child描述的Pictrue Layer的父Picture Layer,并且将参
30、数child描述的Pictrue Layer保存在当前正在处理的Picture Layer的子Picture Layer列表中。 Layer类的成员函数InsertChild所做的第二件事情是调用另外一个成员函数SetNeedsFullTreeSync发出一个通知,要在CC Layer Tree与CC Pending Layer Tree之间做一个Tree结构同步。 Layer类的成员函数SetNeedsFullTreeSync的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片void Layer:SetNeedsFullTreeSync() if (!layer_tree_host_) return; layer_tree_host_-SetNeedsFullTreeSync(); 这个函数定义在文件external/chromium_org/cc/layers/layer.cc中。 Layer类的成员变量layer_tree_host_指向的是一个LayerTreeHost对象,这个LayerTreeHost是用来管理CC Layer Tree的,后面我们再分析它的创建过程。Layer类的成员函数SetNeedsFullTreeSync所做的事情就是调用这个LayerT
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1