Chromium网页Layer Tree创建过程分析.docx
《Chromium网页Layer Tree创建过程分析.docx》由会员分享,可在线阅读,更多相关《Chromium网页Layer Tree创建过程分析.docx(58页珍藏版)》请在冰豆网上搜索。
Chromium网页LayerTree创建过程分析
Chromium网页LayerTree创建过程分析
在Chromium中,WebKit会创建一个GraphicsLayerTree描述网页。
GraphicsLayerTree是和网页渲染相关的一个Tree。
网页渲染最终由Chromium的CC模块完成,因此CC模块又会根据GraphicsLayerTree创建一个LayerTree,以后就会根据这个LayerTree对网页进行渲染。
本文接下来就分析网页LayerTree的创建过程。
从前面一文可以知道,网页的GraphicsLayerTree是根据RenderLayerTree创建的,RenderLayerTree又是根据RenderObjectTree创建的。
GraphicsLayerTree与RenderLayerTree、RenderLayerTree与RenderObjectTree的节点是均是一对多的关系,然而GraphicsLayerTree与CC模块创建的LayerTree的节点是一一对应的关系,如图1所示:
也就是说,每一个GraphicsLayer都对应有一个CCLayer。
不过,GraphicsLayer与CCLayer不是直接的一一对应的,它们是透过另外两个Layer才对应起来的,如图2所示:
中间的两个Layer分别是WebContentLayerImpl和WebLayerImpl,它们是属于Content层的对象。
关于Chromium的层次划分,可以参考前面一文的介绍。
GraphicsLayer与CCLayer的对应关系,是在GraphicsLayer的创建过程中建立起来的,接下来我们就通过源码分析这种对应关系的建立过程。
从前面一文可以知道,GraphicsLayer是通过调用GraphicsLayerFactoryChromium类的成员函数createGraphicsLayer创建的,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
PassOwnPtrGraphicsLayerFactoryChromium:
:
createGraphicsLayer(GraphicsLayerClient*client)
{
OwnPtrlayer=adoptPtr(newGraphicsLayer(client));
......
returnlayer.release();
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/web/GraphicsLayerFactoryChromium.cpp中。
参数client指向的实际上是一个CompositedLayerMapping对象,这个CompositedLayerMapping对象会用来构造一个GraphicsLayer。
GraphicsLayer的构造过程,也就是GraphicsLayer类的构造函数的实现,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
GraphicsLayer:
:
GraphicsLayer(GraphicsLayerClient*client)
:
m_client(client)
......
{
......
m_opaqueRectTrackingContentLayerDelegate=adoptPtr(newOpaqueRectTrackingContentLayerDelegate(this));
m_layer=adoptPtr(Platform:
:
current()->compositorSupport()->createContentLayer(m_opaqueRectTrackingContentLayerDelegate.get()));
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。
GraphicsLayer类的构造函数首先是将参数client指向的CompositedLayerMapping对象保存在成员变量m_client中,接着又创建了一个OpaqueRectTrackingContentLayerDelegate对象保存在成员变量opaqueRectTrackingContentLayerDelegate中。
再接下来GraphicsLayer类的构造函数通过Platform类的静态成员函数current获得一个RendererWebKitPlatformSupportImpl对象。
这个RendererWebKitPlatformSupportImpl对象定义在Content模块中,它实现了由WebKit定义的Platform接口,用来向WebKit层提供平台相关的实现。
通过调用RendererWebKitPlatformSupportImpl类的成员函数compositorSupport可以获得一个WebCompositorSupportImpl对象。
有了这个WebCompositorSupportImpl对象之后,就可以调用它的成员函数createContentLayer创建一个WebContentLayerImpl对象,并且保存在GraphicsLayer类的成员变量m_layer中。
WebCompositorSupportImpl类的成员函数createContentLayer的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
WebContentLayer*WebCompositorSupportImpl:
:
createContentLayer(
WebContentLayerClient*client){
returnnewWebContentLayerImpl(client);
}
这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_compositor_support_impl.cc中。
从这里可以看到,WebCompositorSupportImpl类的成员函数createContentLayer创建了一个WebContentLayerImpl对象返回给调用者。
WebContentLayerImpl对象的创建过程,即WebContentLayerImpl类的构造函数的实现,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
WebContentLayerImpl:
:
WebContentLayerImpl(blink:
:
WebContentLayerClient*client)
:
client_(client),......{
if(WebLayerImpl:
:
UsingPictureLayer())
layer_=make_scoped_ptr(newWebLayerImpl(PictureLayer:
:
Create(this)));
else
layer_=make_scoped_ptr(newWebLayerImpl(ContentLayer:
:
Create(this)));
......
}
这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_content_layer_impl.cc中。
从前面的调用过程可以知道,参数client指向的实际上是一个OpaqueRectTrackingContentLayerDelegate对象,WebContentLayerImpl类的构造函数首先将它保存在成员变量client_中。
WebContentLayerImpl类的构造函数接下来调用WebLayerImpl类的静态成员函数UsingPictureLayer判断Render进程是否启用ImplSidePainting特性。
如果启用的话,就会调用PictureLayer类的静态成员函数Create创建一个PictureLayer;否则的话,就会调用ContentLayer类的静态成员函数Create创建一个ContentLayer。
有了PictureLayer或者ContentLayer之后,再创建一个WebLayerImpl对象,保存在WebContentLayerImpl类的成员变量layer_中。
当Render进程设置了enable-impl-side-painting启动选项时,就会启用ImplSidePainting特性,也就是会在Render进程中创建一个Compositor线程,与Render进程中的Main线程一起协作完成网页的渲染。
在这种情况下,GraphicsLayer在绘制网页内容的时候,实际上只是记录了绘制命令。
这些绘制命令就记录在对应的PictureLayer中。
另一方面,如果Render进程没有设置enable-impl-side-painting启动选项,那么GraphicsLayer在绘制网页内容的时候,就会通过ContentLayer提供的一个Canvas真正地把网页内容对应的UI绘制在一个内存缓冲区中。
无论是PictureLayer还是ContentLayer,它们都是在cc:
:
Layer类继承下来的,也就是说,它们对应于图2所示的CCLayer。
不过,我们只考虑PictureLayer的情况,因此接下来我们继续分析PictureLayer的创建过程,也就是PictureLayer类的静态成员函数Create的实现,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
scoped_refptrPictureLayer:
:
Create(ContentLayerClient*client){
returnmake_scoped_refptr(newPictureLayer(client));
}
这个函数定义在文件external/chromium_org/cc/layers/picture_layer.cc中。
从这里可以看到,PictureLayer类的静态成员函数Create创建了一个PictureLayer对象返回给调用者。
PictureLayer对象的创建过程,也就是PictureLayer类的构造函数的实现,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
PictureLayer:
:
PictureLayer(ContentLayerClient*client)
:
client_(client),
pile_(make_scoped_refptr(newPicturePile())),
......{
}
这个函数定义在文件external/chromium_org/cc/layers/picture_layer.cc中。
从前面的调用过程可以知道,参数client指向的实际上是一个WebContentLayerImpl对象,PictureLayer类的构造函数将它保存在成员变量client_中。
PictureLayer类的构造函数还做了另外一件重要的事情,就是创建了一个PicturePile对象,并且保存在成员变量pile_中。
这个PicturePile对象是用来将GraphicsLayer的绘制命令记录在PictrueLayer中的,后面我们分析网页内容的绘制过程时就会看到这一点。
回到WebContentLayerImpl类的构造函数中,它创建了一个PictrueLayer之后,接下来就会以这个PictrueLayer为参数,创建一个WebLayerImpl对象,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
WebLayerImpl:
:
WebLayerImpl(scoped_refptrlayer):
layer_(layer){
......
}
这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_layer_impl.cc中。
WebLayerImpl类的构造函数主要就是将参数layer描述的一个PictrueLayer对象保存在成员变量layer_中。
从前面一文还可以知道,GraphicsLayer与GraphicsLayer是通过GraphicsLayer类的成员函数addChild形成父子关系的(从而形成GraphicsLayerTree),如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidGraphicsLayer:
:
addChild(GraphicsLayer*childLayer)
{
addChildInternal(childLayer);
updateChildList();
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。
GraphicsLayer类的成员函数addChild首先调用成员函数addChildInternal将参数childLayer描述的一个GraphicsLayer作为当前正在处理的GraphicsLayer的子GraphicsLayer,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidGraphicsLayer:
:
addChildInternal(GraphicsLayer*childLayer)
{
......
childLayer->setParent(this);
m_children.append(childLayer);
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。
这一步执行完成后,GraphicsLayer之间就建立了父子关系。
回到GraphicsLayer类的成员函数addChild中,它接下来还会调用另外一个成员函数updateChildList,用来在CCLayer之间建立父子关系,从而形CCLayerTree。
GraphicsLayer类的成员函数updateChildList的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidGraphicsLayer:
:
updateChildList()
{
WebLayer*childHost=m_layer->layer();
......
for(size_ti=0;ichildHost->addChild(m_children[i]->platformLayer());
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。
从前面的分析可以知道,GraphicsLayer类的成员变量m_layer指向的是一个WebContentLayerImpl对象,调用这个WebContentLayerImpl对象的成员函数layer获得的是一个WebLayerImpl对象,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
blink:
:
WebLayer*WebContentLayerImpl:
:
layer(){
returnlayer_.get();
}
这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_content_layer_impl.cc中。
从前面的分析可以知道,WebContentLayerImpl类的成员变量layer_指向的是一个WebLayerImpl对象,因此WebContentLayerImpl类的成员函数layer返回的是一个WebLayerImpl对象。
回到GraphicsLayer类的成员函数updateChildList中,它接下来调用GraphicsLayer类的成员函数platformLayer获得当前正在处理的GraphicsLayer的所有子GraphicsLayer对应的WebLayerImpl对象,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
WebLayer*GraphicsLayer:
:
platformLayer()const
{
returnm_layer->layer();
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp中。
这些子GraphicsLayer对应的WebLayerImpl对象也就是通过调用它们的成员变量m_layer指向的WebContentLayerImpl对象的成员函数layer获得的。
再回到GraphicsLayer类的成员函数updateChildList中,获得当前正在处理的GraphicsLayer对应的WebLayerImpl对象,以及其所有的子GraphicsLayer对应的WebLayerImpl对象之后,就可以通过调用WebLayerImpl类的成员函数addChild在它们之间也建立父子关系,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidWebLayerImpl:
:
addChild(WebLayer*child){
layer_->AddChild(static_cast(child)->layer());
}
这个函数定义在文件external/chromium_org/content/renderer/compositor_bindings/web_layer_impl.cc中。
从前面的分析可以知道,WebLayerImpl类的成员变量layer_指向的是一个PictrueLayer对象,因此WebLayerImpl类的成员函数addChild所做的事情就是在两个PictrueLayer对象之间建立父子关系,这是通过调用PictrueLayer类的成员函数AddChild实现的。
PictrueLayer类的成员函数AddChild是父类Layer继承下来的,它的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidLayer:
:
AddChild(scoped_refptrchild){
InsertChild(child,children_.size());
}
这个函数定义在文件external/chromium_org/cc/layers/layer.cc中。
Layer类的成员函数AddChild将参数child描述的PictrueLayer设置为当前正在处理的PictureLayer的子PictureLayer,这是通过调用Layer类的成员函数InsertChild实现的,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidLayer:
:
InsertChild(scoped_refptrchild,size_tindex){
DCHECK(IsPropertyChangeAllowed());
child->RemoveFromParent();
child->SetParent(this);
child->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所做的第一件事情是将当前正在处理的PictureLayer设置为参数child描述的PictrueLayer的父PictureLayer,并且将参数child描述的PictrueLayer保存在当前正在处理的PictureLayer的子PictureLayer列表中。
Layer类的成员函数InsertChild所做的第二件事情是调用另外一个成员函数SetNeedsFullTreeSync发出一个通知,要在CCLayerTree与CCPendingLayerTree之间做一个Tree结构同步。
Layer类的成员函数SetNeedsFullTreeSync的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidLayer:
:
SetNeedsFullTreeSync(){
if(!
layer_tree_host_)
return;
layer_tree_host_->SetNeedsFullTreeSync();
}
这个函数定义在文件external/chromium_org/cc/layers/layer.cc中。
Layer类的成员变量layer_tree_host_指向的是一个LayerTreeHost对象,这个LayerTreeHost是用来管理CCLayerTree的,后面我们再分析它的创建过程。
Layer类的成员函数SetNeedsFullTreeSync所做的事情就是调用这个LayerT