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

这篇博客分析的是网页内容更新时(比如滚动),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进程结构分析的第二部分给出了如下类关系:

chromium for android硬件渲染流程全解析(render进程)_第1张图片

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

chromium for android硬件渲染流程全解析(render进程)_第2张图片

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

chromium for android硬件渲染流程全解析(render进程)_第3张图片

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

chromium for android硬件渲染流程全解析(render进程)_第4张图片

其中:

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会确定网页上每个元素的大小,位置等信息,从而为绘制做准备。
这个触发过程如下图:

chromium for android硬件渲染流程全解析(render进程)_第5张图片

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

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

chromium for android硬件渲染流程全解析(render进程)_第6张图片

Picture::Record()中主要做了两件事情:
1).创建具有后端存储(SKBitmap)的SKCanvas;
2).将1)中创建的SKCanvas作为参数,调用WebContentLayerImpl::PaintContents(),触发webkit中网页内容的绘制命令记录到SKCanvas.
下面看这两件事的具体实现。
1).创建具有后端存储(SKBitmap)的SKCanvas,具体过程如下:
Picture::Record()函数中,先创建了skia::SkTileGridPicture,SkTileGridPicture继承自SKPicture.
接着调用SkTileGridPicture::beginRecording(),实际调用的是SkPicture::beginRecording().
SkPicture::beginRecording()的作用就是申请一块SKBitmap,并以这块SKBitmap作为后端存储创建SkPictureRecord,SkPictureRecord继承自SKCanvas.
Picture::Record()调用完SkPicture::beginRecording()后就得到了一块拥有SKBitmap的SKCanvas.
2).将1)中创建的SKCanvas作为参数,调用WebContentLayerImpl::PaintContents(),触发webkit中网页内容的绘制命令记录到SKCanvas上.具体过程如下图:

chromium for android硬件渲染流程全解析(render进程)_第7张图片

Picture::Record()调用WebContentLayerImpl::PaintContents(),同时将新创建的SKCanvas传入。
WebContentLayerImpl::PaintContents()接着调用OpaqueRectTrackingContentLayerDelegate::paintContents(),SKCanvas作为参数传入。
OpaqueRectTrackingContentLayerDelegate::paintContents()中以SkPicture::beginRecording()创建的SKCanvas为参数创建了GraphicsContext。
OpaqueRectTrackingContentLayerDelegate::paintContents()接着调用
GraphicsLayer::paint(),同时新创建的GraphicsContext作为参数传入。
GraphicsLayer::paint()调用GraphicsLayer::paintGraphicsLayerContents()。
注意这里的GraphicsLayer实例是包含在RenderLayerBacking中的成员变量OwnPtr m_graphicsLayer;
GraphicsLayer::paintGraphicsLayerContents()接着调用RenderLayerBacking::paintContents(),接着调用
RenderLayerBacking::paintIntoLayer(),接着调用RenderLayer::paintLayerContents().
这样,就进入了RenderLayerTree的绘制过程,RenderLayer中包含的网页内容的绘制命令保存在了GraphicsContext中封装的SKCanvas上。
前面的讲解,我们知道这块SKCanvas是在SKPicture中创建的,SKPicture包含在Picture中,Picture又包含在PicturePile中,PicturePile包含在PictureLayer中。
PictureLayer包含在LayerTreeHost的成员变量scoped_refptr root_layer_为根结点的Layer Tree中。
这样,当LayerTreeHost::UpdateLayers()执行完后,各层网页内容的绘制命令就包含在了LayerTreeHost的成员变量scoped_refptr root_layer_为根节点的Layer Tree中.
SKPicture,Picture,PicturePile,PictureLayer,layertreehost之间的关系图如下:

chromium for android硬件渲染流程全解析(render进程)_第8张图片

ThreadProxy::BeginFrameOnMainThread()触发的流程
ThreadProxy::BeginFrameOnMainThread()调用ThreadProxy::StartCommitOnImplThread()触发的流程如下图:
chromium for android硬件渲染流程全解析(render进程)_第9张图片     
ThreadProxy::ScheduledActionCommit()中会顺序调用LayerTreeHost的两个重要函数,
LayerTreeHost::BeginCommitOnImplThread();
LayerTreeHost::FinishCommitOnImplThread();
LayerTreeHost::FinishCommitOnImplThread()的任务是将LayerTreeHost中维护的含有网页绘制命令的Layer Tree,提交给LayTreeHostImpl中维护的LayerTreeImpl.
具体的讲,就是LayerTreeHost的root_layer_指向的PictureLayer中存储网页内容绘制命令的PicturePileBase,传给了LayerTreeHostImpl的root_layer_指向的
PictureLayerImpl中存储网页内容绘制命令的PicturePileBase.
PictureLayer包含PicturePile,PicturePile继承自PicturePileBase;
PictureLayerImpl包含PicturePileImpl,PicturePileImpl继承自PicturePileBase;
PicturePileBase中包含实际的网页绘制命令。
上述类之间的关系如下图:

chromium for android硬件渲染流程全解析(render进程)_第10张图片

完成上述过程的关键语句如下:

LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl){
if (needs_full_tree_sync_)
    sync_tree->SetRootLayer(TreeSynchronizer::SynchronizeTrees(
        root_layer(), sync_tree->DetachLayerTree(), sync_tree));
  {
    TRACE_EVENT0("cc", "LayerTreeHost::PushProperties");
    TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer());
  }
}
TreeSynchronizer::SynchronizeTrees()复制Layer tree的结构到LayerImpl tree.
TreeSynchronizer::PushProperties()中完成了将
LayerTreeHost的root_layer_指向的PictureLayer中存储网页内容绘制命令的PicturePileBase,传给了LayerTreeHostImpl的root_layer_指向的
PictureLayerImpl中存储网页内容绘制命令的PicturePileBase.
我们看TreeSynchronizer::PushProperties()的具体实现:
TreeSynchronizer::PushProperties()实际调用的是void PictureLayer::PushPropertiesTo(LayerImpl* base_layer);
void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
  Layer::PushPropertiesTo(base_layer);

  PictureLayerImpl* layer_impl = static_cast(base_layer);
  // This should be first so others can use it.
  layer_impl->UpdateTwinLayer();

  layer_impl->SetIsMask(is_mask_);
  layer_impl->CreateTilingSet();
  // Unlike other properties, invalidation must always be set on layer_impl.
  // See PictureLayerImpl::PushPropertiesTo for more details.
  layer_impl->invalidation_.Clear();
  layer_impl->invalidation_.Swap(&pile_invalidation_);
  layer_impl->pile_ = PicturePileImpl::CreateFromOther(
      pile_.get(), layer_impl->is_using_lcd_text_);
  layer_impl->SyncFromActiveLayer();
}
重点看:
 layer_impl->pile_ = PicturePileImpl::CreateFromOther(
      pile_.get(), layer_impl->is_using_lcd_text_);

scoped_refptr PicturePileImpl::CreateFromOther(
    const PicturePileBase* other,
    bool enable_lcd_text) {
  return make_scoped_refptr(new PicturePileImpl(other, enable_lcd_text));
}

PicturePileImpl::PicturePileImpl(const PicturePileBase* other,
                                 bool enable_lcd_text)
    : PicturePileBase(other),
      enable_lcd_text_(enable_lcd_text),
      clones_for_drawing_(ClonesForDrawing(this, num_raster_threads())) {
}
上面的流程说明PictureLayerImpl中包含的PicturePileImpl的基类实例PicturePileBase与PicturePlayer中包含的PicturePile的基类实例是同一个。
前面对LayerTreeHost::Layout()的分析我们知道,网页的绘制命令就存储在PicturePlayer中包含的PicturePile的基类实例PicturePileBase中。
所以,LayerTreeHost::FinishCommitOnImplThread()执行完后,包含网页绘制命令的结构PicturePileBase被提交给了LayerTreeHostImpl的LayerTreeImpl.

二.发生在实现线程中,网页内容的光栅化,即流程一中的绘制命令
的实际绘制过程,这个过程是在cpu上执行的,绘制过程完成后,
网页内容以像素形式存储在一块SharedMemory上,
这块SharedMemory可以跨进程使用。

ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw)会触发网页内容的实际绘制过程。
网页的绘制过程大致分为:计算坐标变换,光栅化,gl绘制。
ThreadProxy::ScheduledActionDrawAndSwapInternal()中顺序调用了LayerTreeHostImpl的几个重要函数:
LayerTreeHostImpl::PrepareToDraw();
LayerTreeHostImpl::DrawLayers();
LayerTreeHostImpl::SwapBuffers();
LayerTreeHostImpl::PrepareToDraw()触发坐标变换和光栅化的过程如下图:

chromium for android硬件渲染流程全解析(render进程)_第11张图片

layer_tree_host_common.cc定义的全局函数:
template
static void CalculateDrawPropertiesInternal();
会先计算必要的变换,然后调用UpdateTilePrioritiesForLayer()触发光栅化过程。
UpdateTilePrioritiesForLayer()是定义在layer_tree_host_common.cc的全局函数。
我们重点看光栅化过程的触发和具体实现。
1)创建可以覆盖当前Layer更新区域的多个Tile.
这个过程涉及的类图如下:

chromium for android硬件渲染流程全解析(render进程)_第12张图片

调用流程如下图:

chromium for android硬件渲染流程全解析(render进程)_第13张图片

PictureLayerTiling::UpdateTilePriorities()先调用PictureLayerTiling::SetLiveTilesRect()创建Tile,
再为每个Tile设置优先级。
2)为1中创建的每个Tile创建光化任务。

这个过程涉及的类图如下:

chromium for android硬件渲染流程全解析(render进程)_第14张图片

调用流程如下图:

chromium for android硬件渲染流程全解析(render进程)_第15张图片

TileManager和PicturePileImpl之间的关系如下图:

chromium for android硬件渲染流程全解析(render进程)_第16张图片

下面我们看TileManager::CreateRasterTask()的具体实现。
TileManager::CreateRasterTask(Tile* tile)首先为tile申请ResourcePool::Resource.
ResourcePool::Resource对应着一个实际的纹理索引,这个纹理索引由glGenTexture生成。
ResourcePool::AcquireResource()会导致ResourceProvider::CreateManagedResource()被调用。
过程如下图:

chromium for android硬件渲染流程全解析(render进程)_第17张图片

ResourceProvider::CreateManagedResource()会触发真正的glGenTexture的调用,产生Texture的索引.
过程如下图:

chromium for android硬件渲染流程全解析(render进程)_第18张图片

GLES2Implementation::GenTextures()定义在gles2_implementation_impl_autogen.h中,这个文件是自动生成的。
GenTexturesImmediate()定义在gles2_cmd_helper_autogen.h中,这个文件是自动生成的。
GenTexturesImmediate()会发送gles2::cmds::GenTexturesImmediate,
最终调用到GLES2DecoderImpl::HandleGenTexturesImmediate()。定义在gles2_cmd_decoder_autogen.h中,这个文件是自动生成的。
GLES2DecoderImpl::HandleGenTexturesImmediate()调用GLES2DecoderImpl::GenTexturesHelper().
GLES2DecoderImpl::GenTexturesHelper()调用glGenTextures生成纹理索引。
ResourcePool::Resource创建完成后,对应的纹理索引保存在Resource::id_中。
TileManager::CreateRasterTask()中,可以看到这个索引值同时保存在Tile的ManagedTileState::TileVersion::resource_id_中。
TileManager::CreateRasterTask()接着调用RasterWorkerPool::RasterTask的构造函数创建RasterTask.

asterWorkerPool::RasterTask的构造函数需要5个参数,其中第3,4个参数是函数指针:
typedef base::Callback Callback;
typedef base::Callback Reply;
TileManager::CreateRasterTask()调用RasterWorkerPool::RasterTask的构造函数是第三个参数为:
base::Bind(&TileManager::RunAnalyzeAndRasterTask,
                 base::Bind(&TileManager::RunAnalyzeTask,
                            analysis,
                            tile->content_rect(),
                            tile->contents_scale(),
                            use_color_estimator_,
                            GetRasterTaskMetadata(*tile),
                            rendering_stats_instrumentation_),
                 base::Bind(&TileManager::RunRasterTask,
                            analysis,
                            tile->content_rect(),
                            tile->contents_scale(),
                            GetRasterTaskMetadata(*tile),
                            rendering_stats_instrumentation_)),
即RasterWorkerPool::RasterTask的Callback函数指针实际指向的是TileManager::RunAnalyzeAndRasterTask。
3)调度执行光化的过程。
TileManager::ScheduleTasks()先为每个Tile创建光栅化任务,再调用raster_worker_pool_->ScheduleTasks(&tasks);调度光栅化任务的执行。
光栅化任务触发的流程如下图:

chromium for android硬件渲染流程全解析(render进程)_第19张图片

PixelBufferRasterWorkerPool::ScheduleMoreTasks()中调用
resource_provider_->AcquirePixelBuffer(task->resource()->id());创建了Buffer.
接着调用resource_provider_->MapPixelBuffer()得到一块buffer.这块buffer作为参数传递给了
PixelBufferWorkerPoolTaskImpl的构造函数,保存在变量buffer_中。
PixelBufferWorkerPoolTaskImpl定义在pixel_buffer_raster_worker_pool.cc中。
PixelBufferWorkerPoolTaskImpl::RunOnThread()中以buffer_为后端存储创建了SkDevice,并将这个SKDevice传递给了
RasterWorkerPoolTaskImpl::RunOnThread().
RasterWorkerPoolTaskImpl::RunOnThread()调用了TileManager::RunAnalyzeAndRasterTask,并将SKDevice作为参数传入。
这样,resource_provider_->MapPixelBuffer()得到的buffer,就以SKDevice的形式传递到了TileManager::RunRasterTask().
TileManager::RunRasterTask()中以传递进来的SKDevice为参数创建了SKCavas实例。SKCanvas实例作为参数传递给了
PicturePileImpl::RasterToBitmap().完成真正的光栅化过程。光栅化完成后,每个Tile覆盖的当前Layer的内容就以像素的形式存储在
resource_provider_->MapPixelBuffer()得到的那块buffer上了。PicturePileImpl::RasterToBitmap->PicturePileImpl::RasterCommon

->Picture::Raster()->SKPicture::draw()完成具体绘制过程。

4)resource_provider_->MapPixelBuffer()得到的buffer的具体来源。

buffer的创建流程如下图:

chromium for android硬件渲染流程全解析(render进程)_第20张图片

这里分配的SharedMemory的一部分一TileManager管理的Tile对应的texture是一一对应的关系,SharedMemory会作为纹理数据源传给Tile对应的Texture.

三.光栅化后,流程二中存储网页内容的SharedMemory在GPU进程中作为
纹理数据的源上传给gpu,实现纹理贴图(glTexImage2D)。
chromium采用分块渲染的策略,TileManager管理的每个Tile最终
都对应着一块texture(ResourceProvider负责分配).
SharedMemory中的网页内容通过glTexImage2D最终渲染到了Tile对应的texture上。

1)将光化后包含像素的buffer作为纹理数据上传给gpu的过程(glTexImage2D)。
光栅化完成后会调用PixelBufferRasterWorkerPool::OnRasterTaskCompleted(),PixelBufferRasterWorkerPool::OnRasterTaskCompleted()调用
ResourceProvider::BeginSetPixels(),会顺序调用以下重要函数:
context3d->bindTexture();
context3d->bindBuffer();
其中context3d->bindTexture()绑定当前resource对应的Texture.
context3d->bindBuffer()设置当前resource对应的buffer的id.
context3d->asyncTexImage2DCHROMIUM()将光栅化到Buffer上的像素上传给texture。
context3d->asyncTexImage2DCHROMIUM()->GLES2Implementation::AsyncTexImage2DCHROMIUM().
GLES2Implementation::AsyncTexImage2DCHROMIUM(){
 helper_->AsyncTexImage2DCHROMIUM(
        target, level, internalformat, width, height, border, format, type,
        buffer->shm_id(), buffer->shm_offset() + offset);
}可以看到SharedMemory的封装类BufferTracker::Buffer的地址传给了helper_->AsyncTexImage2DCHROMIUM。
helper_->AsyncTexImage2DCHROMIUM最终会调用到GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM()定义在gles2_cmd_decoder.cc中。
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM()会调用AsyncPixelTransferDelegateEGL::AsyncTexImage2D(),
AsyncPixelTransferDelegateEGL::AsyncTexImage2D()会接着调用TransferStateInternal::PerformAsyncTexImage2D()定义在Async_Pixel_Transfer_Delegate_egl.cc中。
TransferStateInternal::PerformAsyncTexImage2D()最终会调用glTexImage2D或glTexSubImage2D。将光栅化到Buffer上的像素上传给纹理映射。
glTexImage2D加载图像数据。
.LayerTreeHostImpl::CalculateRenderPasses()记录已经光栅化的需要绘制的Tile的信息,为LayerTreeHostImpl::DrawLayers()做准备.
LayerTreeHostImpl::PrepareToDraw()调用完 active_tree_->UpdateDrawProperties();触发了光栅化并将网页数据上传给Tile对应的texture之后,调用
LayerTreeHostImpl::CalculateRenderPasses()为LayerTreeHostImpl::DrawLayers()做准备。
LayerTreeHostImpl::CalculateRenderPasses()主要作用是为二中每个texture中已经加载了纹理数据的Tile创建TileDrawQuad并添加到FrameData类型的变量中。
LayerTreeHostImpl::DrawLayers()最终绘制的就是包含在FrameData类型的变量中的TileDrawQuad对应的texture。

TileDrawQuad包含的信息是需要渲染的已经加载了网页数据的texture的信息。
LayerTreeHostImpl::CalculateRenderPasses()首先为每一个LayerImpl中包含的RenderSurfaceImpl变量调用AppendRenderPasses创建一个RenderPass,
并添加到FrameData类型变量中。
接着对FrameData中包含的所有LayerImpl调用AppendQuadsForLayer(),AppendQuadsForLayer定义在Layer_tree_host_impl.cc中的全局函数。
AppendQuadsForLayer()调用具体LayerImpl的AppendQuads().
对于Render进程LayerImpl的具体类型是PictureLayerImpl;对于Brower进程LayerImpl的具体类型是TextureLayerImpl。
PictureLayerImpl::AppendQuads()中会遍历PictureLayerTilingSet类型的变量tilings_,为每一个对应texture已经加载了网页数据的Tile创建一个TileDrawQuad实例,
这个实例被添加到FrameData类型变量间接包含的QuadList中。
这个过程中涉及的类关系图如下:

chromium for android硬件渲染流程全解析(render进程)_第21张图片

LayerTreeHostImpl::CalculateRenderPasses()执行完后,对应texture已经加载了网页数据的Tile的信息以TileDrawQuad的形式包含在FrameData类型的变量中。
这个FrameData类型的变量被传递给了LayerTreeHostImpl::DrawLayers()。

.LayerTreeHostImpl::DrawLayers()触发的实际的绘制过程。(glDrawElements).
这个过程会先调用glFramebufferTexture2DEXT,将texture attach到render进程
创建的off-screen surface对应的framebuffer object上,再接着对每个Tile
对应的texture调用glDrawElements,这个过程完成后,网页内容就被渲染到了
attach到framebuffer上的textures上了,这些texture会被传递给browser进程。

chromium for android硬件渲染流程全解析(render进程)_第22张图片

DirectRenderer::DrawFrame()->GLRenderer::BeginDrawingFrame()->
GLRenderer::EnsureBackbuffer()->
MailboxOutputSurface::EnsureBackbuffer(){
current_backing_.texture_id = context3d_->createTexture();
current_backing_.size = size_;
context3d_->genMailboxCHROMIUM(current_backing_.mailbox.name);
context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id);
}
EnsureBackbuffer()中生成一个texture,为这个texture生成一个mailbox,绑定这个texture.
这个texture会在MailboxOutputSurface::BindFramebuffer(){
context3d_->framebufferTexture2D(
      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
      current_backing_.texture_id, 0);
}中attach到framebuffer object的color attachment上。
以下是MailboxOutputSurface::BindFramebuffer()的触发流程:
DirectRenderer::DrawRenderPass()->DirectRenderer::UseRenderPass()->
GLRenderer::BindFramebufferToOutputSurface()->
MailboxOutputSurface::BindFramebuffer().
上述过程完成后,就可以对流程四中每个Texture进行实际的渲染过程,即调用glDrawElements。
GLRenderer::DoDrawQuad()调用GLRenderer::DrawTileQuad().
GLRenderer::DrawQuadGeometry()调用
WebGraphicsContext3DCommandBufferImpl->drawElements()最终会调用到
GLES2DecoderImpl::HandleDrawElements().
GLES2DecoderImpl::HandleDrawElements()会调用GLES2DecoderImpl::DoDrawElements()。
GLES2DecoderImpl::DoDrawElements()定义在gles2_cmd_decoder.cc中。
GLES2DecoderImpl::DoDrawElements()会调用glDrawElements进行实际的渲染。
这个过程执行完,网页内容就渲染到了MailboxOutputSurface::EnsureBackbuffer()
中创建的texture上。
渲染结结束后DirectRenderer::DrawFrame()->GLRenderer::FinishDrawingFrame()
->MailboxOutputSurface::SendFrameToParentCompositor(){
 frame->gl_frame_data.reset(new GLFrameData());
  DCHECK(!size_.IsEmpty());
  DCHECK(size_ == current_backing_.size);
  DCHECK(!current_backing_.mailbox.IsZero());
 context3d_->framebufferTexture2D(
      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
  context3d_->bindFramebuffer(GL_FRAMEBUFFER, 0);
  context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id);
   context3d_->produceTextureCHROMIUM(
      GL_TEXTURE_2D, current_backing_.mailbox.name);
  frame->gl_frame_data->mailbox = current_backing_.mailbox;
  frame->gl_frame_data->size = current_backing_.size;
  context3d_->flush();
  frame->gl_frame_data->sync_point = context3d_->insertSyncPoint();
  CompositorOutputSurface::SendFrameToParentCompositor(frame);
 pending_textures_.push_back(current_backing_);
  current_backing_ = TransferableFrame();
}
其中:
1.context3d_->produceTextureCHROMIUM()产生可被Browser进程消耗的Texture,
即render进程中渲染到的目标texture;
2.将包含目标texture的mailbox name设置在frame变量中,并通过
CompositorOutputSurface::SendFrameToParentCompositor(frame)发送给browser进程。
browser进程通过mailbox name找到Render进程产生的texture.这个过程下一篇写。


你可能感兴趣的:(chromium for android硬件渲染流程全解析(render进程))