Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx

上传人:b****4 文档编号:6287668 上传时间:2023-05-06 格式:DOCX 页数:110 大小:202.84KB
下载 相关 举报
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第1页
第1页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第2页
第2页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第3页
第3页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第4页
第4页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第5页
第5页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第6页
第6页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第7页
第7页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第8页
第8页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第9页
第9页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第10页
第10页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第11页
第11页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第12页
第12页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第13页
第13页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第14页
第14页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第15页
第15页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第16页
第16页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第17页
第17页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第18页
第18页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第19页
第19页 / 共110页
Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx_第20页
第20页 / 共110页
亲,该文档总共110页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx

《Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx(110页珍藏版)》请在冰点文库上搜索。

Chromium硬件加速渲染的UI合成过程资料Word格式文档下载.docx

ActiveLayerTree代表的是一个可以被Browser端合成的UI。

LayerTree和PendingLayerTree的存在使得Render线程和Compositor线程可以并发绘制网页的UI,如图2所示:

这相当于是网页UI的某一帧绘制分为两部分。

前半部分由Render线程处理,后半部分由Compositor线程处理。

其中,第N+1帧的前半部分和第N帧的后半部分可以并发处理。

这一点类似于Android5.0应用程序UI硬件加速渲染机制,具体可以参考这个系列的文章。

其中,这里的Render线程和Compositor线程就相当于Android5.0应用程序进程中的Main线程和Render线程。

从前面一文可以知道,Render端执行GPU命令绘制网页UI时,只不过是将要执行的GPU写入到一个GPU命令缓冲区中,然后由GPU进程从这个GPU命令缓冲区读出GPU命令,并且调用相应的OpenGL函数执行它们。

这个过程实际上是增加了网页渲染过程中的并行度,也就是Render端在GPU命令缓冲区写入GPU命令的同时,GPU进程从GPU命令缓冲区读出GPU命令进行处理。

这样可以很好地利用设备的多核特性。

这一点也是Chromium的硬件加速渲染与Android的硬件加速渲染的重要区别之一。

PendingLayerTree和ActiveLayerTree的存在使用Browser端在任何时刻都有网页UI可以合成。

ActiveLayerTree描述网页内容发生变化前的一帧UI。

对PendingLayerTree进行光栅化是一个漫长的过程。

如果没有ActiveLayerTree的存在,那么就会导致在PendingLayerTree光栅化期间,Browser端没有网页UI可以显示在屏幕上。

早期,Render端先通过一个称为GLRenderer的渲染器将ActiveLayerTree绘制在一个纹理中,然后再将绘制好的纹理传递给Browser端合成,如图3所示:

ActiveLayerTree中的每一个Layer都对应有一个RenderPass,这些RenderPass组成一个RenderPassList。

其中,每一个RenderPass又包含有一个QuadList。

QuadList由一系列的DrawQuad组成。

一个DrawQuad描述的是一个纹理绘制命令,这个纹理绘制命令指定了纹理对象和纹理坐标等信息。

前面提到,WebGL端负责绘制网页中的canvas标签。

这个canvas标签的内容被绘制在一个纹理中。

这个纹理是在WebGL端OpenGL上下文中生成的,然后通过Mailbox传递给Render端。

前面提到,网页中的canvas标签被抽象为一个TextureLayer对象。

这个TextureLayer对象在RenderPassList中对应有一个RenderPass。

这个RenderPass的QuadList包含有一个TextureDrawQuad。

这个TextureDrawQuad指定的纹理对象描述的就是canvas标签的UI。

换句话说,就是WebGL端将canvas标签的UI绘制在一个纹理上。

注意,这个纹理对象是在WebGL端OpenGL上下文中生成的,Render端OpenGL上下文不能直接访问它。

为了使得Render端可以访问这个纹理对象,WebGL端通过Mailbox将这个纹理对象传递给Render端,这样Render端就可以访问它了。

Render端最后通过GLRenderer将RenderPassList的所有RenderPass,包括canvas标签对应的RenderPass,都绘制在一个纹理中。

这个纹理接下来又会通过Mailbox传递给Browser端。

Browser端像Render端一样,也是将自己要绘制的UI(包括了从Render端传递过来的纹理对象)抽象成LayerTree、PendingLayerTree和ActiveLayerTree三棵Tree。

Browser端的ActiveLayerTree也是对应有一个RenderPassList。

这个RenderPassList最终也是通过一个GLRenderer进行绘制。

不过,这个RenderPassList将会被绘制在屏幕中,而不是被绘制在一个纹理中。

从前面的分析就可以知道,通过GLRenderer,Render端首先将自己的RenderPassList绘制在一个纹理中。

这个纹理传递给Broswer端后,再次被绘制在屏幕中。

这意味着Render端的UI被绘制了两次。

第一次在Render端OpenGL上下文中绘制,第二次是在Browser端OpenGL上下文中绘制。

实际上,我们可以直接将Render端的RenderPassList传递给Browser端绘制。

这样就可以减少一次绘制,从而提高效率。

将Render端的RenderPassList传递给Browser端是通过一个称为DelegatedRenderer的渲染器实现的,如图4所示:

Render端的RenderPassList经过DelegatedRenderer处理后,形成一个CompositorFrame。

这个CompositorFrame传递给Browser端之后,就会形成Browser端的ActiveLayerTree中的一个Layer,从而被绘制在屏幕中。

Render端的RenderPassList包含的纹理对象,包括WebGL端生成的纹理对象,都是通过Mailbox传递给Browser端访问的。

在上面的描述过程中,我们提到了LayerTree、PendingLayerTree、ActiveLayerTree、RenderThread、CompositorThread、RenderPass、DrawQuad、GLRenderer、DelegatedRenderer和CompositorFrame等概念,它们都是属于Chromium中的Compositor模块的概念。

Chromium中的Compositor模块简称为CC模块,它负责合成Render端和Browser的UI,在接下来的分析过程中,我们只是简单涉及到它的内容。

在以后分析网页渲染的文章中,我们会再详细分析CC模块的实现原理。

在上面的描述过程中,我们一再提到了Chromium的Mailbox机制,它在Browser端合成Render端和WebGL端UI的过程中起到传递资源的作用,使得一个OpenGL上下文可以访问在另外一个OpenGL上下文中创建的资源。

因此,接下来我们就首先分析Chromium的Mailbox机制。

Mailbox的定义很简单,就是一个名称,如下所示:

[cpp]viewplaincopy

structGPU_EXPORTMailbox{

Mailbox();

boolIsZero()const;

voidSetZero();

voidSetName(constint8_t*name);

//Generateauniqueunguessablemailboxname.

staticMailboxGenerate();

......

int8_tname[GL_MAILBOX_SIZE_CHROMIUM];

};

这个结构体定义在文件external/chromium_org/gpu/command_buffer/common/mailbox.h中。

从这里可以看到,Mailbox的名称使用一个int8_t数组name描述。

一个有效的Mailbox的名称是非0的,也就是数组name不是全0的。

在创建一个Mailbox的时候,它的名称默认被设置为0,如下所示:

Mailbox:

:

Mailbox(){

memset(name,0,sizeof(name));

}

这个函数定义在文件external/chromium_org/gpu/command_buffer/common/mailbox.cc中。

以后我们可以通过Mailbox结构体的成员函数SetName设置一个Mailbox的名称,如下所示:

voidMailbox:

SetName(constint8*n){

DCHECK(IsZero()||!

memcmp(name,n,sizeof(name)));

memcpy(name,n,sizeof(name));

还可以通过Mailbox结构体的成员函数SetZero将一个Mailbox的名称设置为0,如下所示:

SetZero(){

Mailbox结构体还提供了成员函数IsZero判断一个Mailbox的名称是否为0,如下所示:

boolMailbox:

IsZero()const{

for(size_ti=0;

i<

arraysize(name);

++i){

if(name[i])

returnfalse;

}

returntrue;

我们可以通过Mailbox类静态成员函数Generate生成一个名称不为0的Mailbox,如下所示:

MailboxMailbox:

Generate(){

Mailboxresult;

//Generatescryptographically-securebytes.

base:

RandBytes(result.name,sizeof(result.name));

returnresult;

一般来说,我们不直接调用Mailbox类静态成员函数Generate生成一个Mailbox,而是通过OpenGL接口类GLES2Implementation的成员函数GenMailboxCHROMIUM生成,如下所示:

voidGLES2Implementation:

GenMailboxCHROMIUM(

GLbyte*mailbox){

gpu:

Mailboxresult=gpu:

Generate();

memcpy(mailbox,result.name,sizeof(result.name));

这个函数定义在文件external/chromium_org/gpu/command_buffer/client/gles2_implementation.cc中。

生成的Mailbox通过输出参数mailbox返回给调用者。

调用者获得生成的Mailbox之后,继续调用GLES2Implementation的成员函数ProduceTextureCHROMIUM将该Mailbox与一个纹理对象进行关联,如下所示:

ProduceTextureCHROMIUM(GLenumtarget,

constGLbyte*data){

helper_->

ProduceTextureCHROMIUMImmediate(target,data);

CheckGLError();

参数data描述的是一个Mailbox,另外一个参数target描述的是要关联的纹理对象。

从前面一文可以知道,GLES2Implementation类的成员变量helper_指向的是一个GLES2CmdHelper对象,这里调用它的成员函数ProduceTextureCHROMIUMImmediate向GPU命令缓冲区写入一个gles2:

cmds:

ProduceTextureCHROMIUMImmediate命令,以便传递给GPU进程处理。

GPU进程将gles2:

ProduceTextureCHROMIUMImmediate命令分发给GLES2DecoderImpl类的成员函数DoProduceTextureCHROMIUM处理,处理过程如下所示:

voidGLES2DecoderImpl:

DoProduceTextureCHROMIUM(GLenumtarget,

TextureRef*texture_ref=texture_manager()->

GetTextureInfoForTarget(

&

state_,target);

ProduceTextureRef("

glProduceTextureCHROMIUM"

texture_ref,target,data);

这个函数定义在文件external/chromium_org/gpu/command_buffer/service/gles2_cmd_decoder.cc中。

GLES2DecoderImpl类的成员函数DoProduceTextureCHROMIUM首先调用成员函数texture_manager获得一个TextureManager对象。

这个TextureManager对象负责管理当前正在使用的OpenGL上下文所在的共享组的纹理对象。

有了这个TextureManager对象之后,就可以调用它的成员函数GetTextureInfoForTarget获得参数target描述的纹理引用对象。

有了这个纹理引用对象之后,GLES2DecoderImpl类的成员函数DoProduceTextureCHROMIUM接下来调用另外一个成员函数ProduceTextureRef执行下一步操作。

GLES2DecoderImpl类的成员函数ProduceTextureRef的实现如下所示:

ProduceTextureRef(std:

stringfunc_name,

TextureRef*texture_ref,GLenumtarget,constGLbyte*data){

constMailbox&

mailbox=*reinterpret_cast<

constMailbox*>

(data);

.......

Texture*produced=texture_manager()->

Produce(texture_ref);

group_->

mailbox_manager()->

ProduceTexture(target,mailbox,produced);

GLES2DecoderImpl类的成员函数ProduceTextureRef首先将参数data强制转换成一个Mailbox结构体,接着又调用前面描述的TextureManager对象的成员函数Produce获得参数texture_ref描述的纹理引用对象所引用的纹理对象,如下所示:

Texture*TextureManager:

Produce(TextureRef*ref){

DCHECK(ref);

returnref->

texture();

这个函数定义在文件external/chromium_org/gpu/command_buffer/service/texture_manager.cc中。

TextureManager类的成员函数Produce调用参数ref描述的TextureRef对象的成员函数texture即可获得它所引用的纹理对象。

这个纹理对象使用一个Texture对象描述。

回到GLES2DecoderImpl类的成员函数ProduceTextureRef中,它接下来调用成员变量group_指向的一个ContextGroup对象的成员函数mailbox_manager获得一个MailboxManager对象。

有了这个MailboxManager对象之后,就调用它的成员函数ProduceTexture执行下一步操作。

GLES2DecoderImpl类的成员变量group_指向的ContextGroup对象描述的是一个资源共享组,调用这个ContextGroup对象的成员函数mailbox_manager获得的MailboxManager对象用来管理当前正在使用的OpenGL上下文所属的OpenGL上下文共享组的那些被Mailbox引用的纹理对象。

这意味着在同一个OpenGL上下文共享组的不同OpenGL上下文,可以直接访问与OpenGL上下文共享组关联的MailboxManager对象所管理的纹理对象,这是因为在同一个OpenGL上下文共享组的不同OpenGL上下文本来就是可以相互访问各自创建的纹理对象的。

这一点我们后面可以看到。

上面我们提到了资源共享组和OpenGL上下文共享组,它们的区别可以参考前面一文。

现在我们继续分析MailboxManager类的成员函数ProduceTexture的实现,如下所示:

voidMailboxManager:

ProduceTexture(unsignedtarget,

mailbox,

Texture*texture){

TargetNametarget_name(target,mailbox);

InsertTexture(target_name,texture);

这个函数定义在文件external/chromium_org/gpu/command_buffer/service/mailbox_manager.cc中。

参数texture指向的Texture对象实际上就是参数target描述的纹理对象。

MailboxManager类的成员函数ProduceTexture所要做的事情就是将这个纹理对象与参数mailbox描述的Mailbox关联起来,也就是以参数target和参数mailbox组成的一个TargetName对象为键值,把参数texture描述的纹理对象保存在MailboxManager类的成员变量mailbox_to_textures_描述的一个std:

map中。

这是通过调用MailboxManager类的成员函数InsertTexture实现的,如下所示:

InsertTexture(TargetNametarget_name,Texture*texture){

texture->

SetMailboxManager(this);

TextureToMailboxMap:

iteratortexture_it=

textures_to_mailboxes_.insert(std:

make_pair(texture,target_name));

mailbox_to_textures_.insert(std:

make_pair(target_name,texture_it));

DC

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2