chromium for android硬件渲染流程全解析(render进程)

本文详细剖析了Chromium for Android的渲染流程,从Render进程的布局更新到LayerTree的绘制,再到光栅化和GPU纹理上传的过程,深入理解网页内容如何在Android设备上呈现。
摘要由CSDN通过智能技术生成
这篇博客分析的是网页内容更新时(比如滚动),render进程将新的网页内容渲染到off-screen surface的完整流程。
render进程创建的是off-screen surface(不能显示在屏幕上)。渲染到off-screen surface是通过
framebuffer object进行的,实际渲染目标是attach在framebuffer object上的texture或renderbuffer。
framebuffer object 有三个attachment point:
color attachment point:可以是mip-level的2D texture,也可以是renderbuffer object;
depth attachment point:可以是mip-level的2D texture,也可以是renderbuffer object;
stencil attachment point:只能是renderbuffer object.
render进程的渲染过程完成后,网页内容将被渲染到attach在framebuffer object上的textures上。
这些textures随后通过mailbox被传给了browser进程,browser进程的作用就是合成这些texture到
on-srceen surface上,即将包含网页内容的这些textures合成到on-screen surface对应的back buffer上,
当browser进程调用eglswapbuffer,前后buffer互换,下次屏幕刷新时,在front buffer中的网页内容就会显示
在屏幕上,browser进程中的渲染过程在下一篇介绍。
我把Render进程的整个处理流程分成五个大的子流程:
一.发生在主线程中,网页内容绘制命令被存储在LayerTreeHostImpl包含的LayerTreeImpl中。
二.发生在实现线程中,网页内容的光栅化,即流程一中的绘制命令的实际绘制过程,这个过程是在cpu上执行的,
绘制过程完成后,网页内容以像素形式存储在一块SharedMemory上,注意,这块SharedMemory可以跨进程使用。
三.光栅化后,流程二中存储网页内容的SharedMemory在GPU进程中作为纹理数据的源上传给gpu,
实现纹理贴图(glTexImage2D)。chromium是分块渲染的策略,TileManager管理的每个Tile最终都对应着一块
texture(ResourceProvider负责分配的),SharedMemory中的网页内容通过glTexImage2D最终渲染到了Tile
对应的texture上。
四.LayerTreeHostImpl::CalculateRenderPasses()记录已经光栅化的需要绘制的Tile的信息,
为LayerTreeHostImpl::DrawLayers()做准备.
五.LayerTreeHostImpl::DrawLayers()触发的实际的绘制过程。(glDrawElements).
这个过程会先调用glFramebufferTexture2DEXT,将texture attach到render进程创建的off-screen surface对应的
framebuffer object上,再接着对每个Tile对应的texture调用glDrawElements,这个过程完成后,
网页内容就被渲染到了attach到framebuffer上的textures上了,这些texture会被传递给browser进程。
我们分别看这五个子流程的具体实现。
一. 发生在主线程中,网页内容绘制命令被存储在LayerTreeHostImpl包含的LayerTreeImpl中。
网页内容更新(比如网页滚动,页面刷新,js动画等)时,会触发WebKit::RenderLayer::setBackingNeedsRepaintInRect()的执行。
chromium for android render进程结构分析中介绍过,网页内容绘制命令先被存储在cc::PictureLayer结构中。

chromium for android render进程结构分析的第二部分给出了如下类关系:

WebKit::RenderLayer::setBackingNeedsRepaintInRect()触发cc::PictureLayer::SetNeedsDisplayRect的过程如下图:

这样网页内容更新的处理转移到了cc模块中。
cc模块中由cc::PictureLayer::SetNeedsDisplayRect()函数开始的处理过程如下图:

ThreadProxy::BeginFrameOnMainThread()中顺序调用了如下几个重要函数:

其中:

2.LayerTreeHost::Layout()会触发webkit中包含页面内容的RenderLayerTree的Layout,
RenderLayerTree的Layout会确定网页上每个元素的大小,位置等信息,从而为绘制做准备。
3.LayerTreeHost::UpdateLayers()会触发webkit中包含页面内容的RenderLayerTree的绘制,
这里的绘制指的是将RenderLayerTree中包含的网页内容的绘制命令
存储到GraphicsLayer间接包含的PictureLayer中。
5.ThreadProxy::StartCommitOnImplThread()最终会使LayerTreeHost中维护的含有网页绘制命令的Layer Tree,提交给LayTreeHostImpl中维护的LayerTreeImpl。

下面依次看这三个函数的执行流程。

LayerTreeHost::Layout()触发的流程

LayerTreeHost::Layout()会触发webkit中包含页面内容的RenderLayerTree的Layout,
RenderLayerTree的Layout会确定网页上每个元素的大小,位置等信息,从而为绘制做准备。
这个触发过程如下图:

RenderView是RenderLayerTree的根节点,RenderView开始的Layout会触发整个RenderLayerTree的Layout.

LayerTreeHost::UpdateLayers()触发的流程
LayerTreeHost::UpdateLayers()会触发webkit中包含页面内容的RenderLayerTree的绘制,这里的绘制指的是将RenderLayerTree中包含的网页内容的绘制命令
存储到GraphicsLayer间接包含的PictureLayer中。
由LayerTreeHost::UpdateLayers()开始的流程如下图:

Picture::Record()中主要做了两件事情:
1).创建具有后端存储(SKBitmap)的SKCanvas;
2).将1)中创建的SKCanvas作为参数,调用WebContentLayerImpl::PaintContents(),触发webkit中网页内容的绘制命令记录到SKCanvas.
下面看这两件事的具体实现。
1).创建具有后端存储(SKBitmap)的SKCanvas,具体过程如下:
Picture::Record()函数中,先创建了skia::SkTileGridPictur

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值