基于Flutter 1.5,从源码视角来深入剖析flutter渲染机制,相关源码目录见文末附录
一、GPU线程渲染
看Flutter的渲染绘制过程的核心过程包括在ui线程和gpu线程,上一篇文章Flutter渲染机制—UI线程已经详细介绍了UI线程的工作原理, 本文则介绍GPU线程的工作原理,这里需要注意的是,gpu线程是指运行着GPU Task Runner的名叫gpu的线程,其实依然是是在CPU上执行,用于将ui线程传递过来的layer tree转换为GPU命令并方法送到GPU,但这个执行过程会等待GPU的执行结果。
1.1 GPU渲染原理
1.1.1 GPU渲染概览
gpu线程的主要工作是将layer tree进行光栅化再发送给GPU,其中最为核心方法ScopedFrame::Raster(),其主要工作如下所示:
- LayerTree::Preroll: 绘制前的一些准备工作
- LayerTree::Paint: 此处会嵌套调用各个不同的layer的绘制方法
- SkCanvas::Flush: 将数据flush到GPU,需要注意的是saveLayer的耗时;
- AndroidContextGL::SwapBuffers: 缓存交换操作
1.1.2 生产者-消费者模式
- 当管道中待处理的光栅化任务等于2个的时候(池子满了),则UI线程无法执行Animator::BeginFrame(),而是等于下一次Vsync信号再尝试执行;
- 当管道中没有待处理的光栅化任务的时候(池子空了),则GPU线程无法执行Rasterizer::Draw(),而是直接返回,等待UI线程向其添加任务。
1) 管道Pipeline中的信号量available_
- 在Animator初始化过程会设置初始值available_ = 0
- UI线程执行ProducerCommit(),则available_加1
- 当available_ > 0,允许GPU线程来执行Consume(),则available_减1
2)管道Pipeline中的信号量empty_
- 在Animator初始化过程会设置初始值empty_ = 2
- UI线程执行Produce(),生产layer tree交给GPU线程光栅化操作一次,则执行empty_.TryWait(),也就是empty_减1
- GPU线程执行完成Consume(),则执行empty_.Signal(),也就是empty_加1;
1.1.3 Timeline说明
这几个过程是Timeline中ui线程的标签项,如图所示:

UI线程是”PipelineProduce“,相对应的GPU线程则是”PipelineConsume“,贯穿整个Rasterizer::DoDraw()过程。
1.2 GPU线程绘制流程

Flutter渲染机制在UI线程执行到compositeFrame()过程经过多层调用,将栅格化的任务Post到GPU线程来执行。GPU线程一旦空闲则会执行Rasterizer的draw()操作。图中LayerTree::Paint()过程是一个比较重要的操作,会嵌套调用不同layer的Paint过程,比如TransformLayer,PhysicalShapeLayer,ClipRectLayer,PictureLayer等都执行完成会执行flush()将数据发送给GPU。
1.3 核心类图
1.3.1 Surface类图

三种不同的AndroidSurface,见小节2.6.3,说明如下:
- 硬件VSYNC方式,且开启VULKAN,则采用AndroidSurfaceVulkan,这是当前默认的方式;
- 硬件VSYNC方式,且未开启VULKAN,则采用AndroidSurfaceGL;
- 使用软件模拟的VSYNC方式,则采用AndroidSurfaceSoftware;
1.3.2 Layer类图

LayerTree的root_layer来源于SceneBuilder过程初始化,第一个调用PushLayer()的layer便成为root_layer_,后面的调用会形成一个树状结构。从上图,可知ContainerLayer共有9个子类,由这些子类组合成为了一个layer tree,具体的组合方式取决于业务使用方,在LayerTree的Prepoll和Paint过程便会调用这些layer的方法,下面来看看这9个类:
- ClipRectLayer:矩形裁剪层,可指定矩形和裁剪行为参数,其中裁剪行为有Clip.none,hardEdge,antiAlias,antiAliasWithSaveLayer四种行为;
- ClipRRectLayer:圆角矩形裁剪层,可指定圆角矩形和裁剪行为参数,同上四种行为;
- ClipPathLayer:路径裁剪层,可指定路径和裁剪行为参数,同上四种行为;
- OpacityLayer:透明层,可指定透明度和偏移量参数,其中偏移量是指从画布坐标系原点到调用者坐标系原点的偏移量;
- ShaderMaskLayer:着色层,可指定着色器、矩阵和混合模式参数;
- ColorFilterLayer:颜色过滤层,可指定颜色和混合模式参数;
- Transformayer:变换图层,可指定转换矩阵参数;
- BackdropFilterLayer:背景过滤层,可指定背景图参数;
- PhysicalShapeLayer:物理形状层,可指定颜色等八个参数。
二、源码解读GPU线程渲染
2.1 MessageLoopImpl::RunExpiredTasks
[-> flutter/fml/message_loop_impl.cc]
1void MessageLoopImpl::RunExpiredTasks() { 2 TRACE_EVENT0("fml", "MessageLoop::RunExpiredTasks"); 3 std::vector<fml::closure> invocations; 4 5 { 6 std::lock_guard<std::mutex> lock(delayed_tasks_mutex_); 7 //当没有待处理的task则直接返回 8 if (delayed_tasks_.empty()) { 9 return; 10 } 11 12 auto now = fml::TimePoint::Now(); 13 while (!delayed_tasks_.empty()) { 14 const auto& top = delayed_tasks_.top(); 15 if (top.target_time > now) { 16 break; 17 } 18 invocations.emplace_back(std::move(top.task)); 19 delayed_tasks_.pop(); 20 } 21 22 WakeUp(delayed_tasks_.empty() ? fml::TimePoint::Max() 23 : delayed_tasks_.top().target_time); 24 } 25 26 for (const auto& invocation : invocations) { 27 invocation(); // [见小节2.2] 28 for (const auto& observer : task_observers_) { 29 observer.second(); 30 } 31 } 32}
gpu线程是不断循环处理消息的过程。
2.1.1 Shell::OnAnimatorDraw
[-> flutter/shell/common/shell.cc]
1void Shell::OnAnimatorDraw( 2 fml::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) { 3 4 //向GPU线程提交绘制任务 5 task_runners_.GetGPUTaskRunner()->PostTask( 6 [rasterizer = rasterizer_->GetWeakPtr(), 7 pipeline = std::move(pipeline)]() { 8 if (rasterizer) { 9 rasterizer->Draw(pipeline); //[见小节2.2] 10 } 11 }); 12}
书接上文Flutter渲染机制—UI线程的[小节4.10.5]的Shell::OnAnimatorDraw()方法,向gpu线程post任务,交由gpu线程来处理。
2.2 Rasterizer::Draw
[-> flutter/shell/common/rasterizer.cc]
1void Rasterizer::Draw( 2 fml::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) { 3 TRACE_EVENT0("flutter", "GPURasterizer::Draw"); 4 5 flutter::Pipeline<flow::LayerTree>::Consumer consumer = 6 std::bind(&Rasterizer::DoDraw, this, std::placeholders::_1); 7 8 //消费pipeline的任务 [见小节2.3] 9 switch (pipeline->Consume(consumer)) { 10 case flutter::PipelineConsumeResult::MoreAvailable: { 11 task_runners_.GetGPUTaskRunner()->PostTask( 12 [weak_this = weak_factory_.GetWeakPtr(), pipeline]() { 13 if (weak_this) { 14 weak_this->Draw(pipeline); 15 } 16 }); 17 break; 18 } 19 default: 20 break; 21 } 22}
执行完Consume()后返回值为PipelineConsumeResult::MoreAvailable,则说明还有任务需要处理,则再次执行不同LayerTree的Draw()过程。
2.3 Pipeline::Consume
[-> flutter/synchronization/pipeline.h]
1PipelineConsumeResult Consume(Consumer consumer) { 2 if (consumer == nullptr) { 3 return PipelineConsumeResult::NoneAvailable; 4 } 5 6 // 当ui线程生产了layer tree,则此处可消费 7 if (!available_.TryWait()) { 8 return PipelineConsumeResult::NoneAvailable; 9 } 10 11 ResourcePtr resource; 12 size_t trace_id = 0; 13 size_t items_count = 0; 14 15 { 16 std::lock_guard<std::mutex> lock(queue_mutex_); 17 //从队列中取出头部的资源 18 std::tie(resource, trace_id) = std::move(queue_.front()); 19 queue_.pop(); 20 items_count = queue_.size(); 21 } 22 23 { 24 TRACE_EVENT0("flutter", "PipelineConsume"); 25 consumer(std::move(resource)); //消费管道中的一项资源[见小节2.4] 26 } 27 28 //消费完成,则将消息量empty_执行加1操作 29 empty_.Signal(); 30 TRACE_FLOW_END("flutter", "PipelineItem", trace_id); 31 return items_count > 0 ? PipelineConsumeResult::MoreAvailable 32 : PipelineConsumeResult::Done; 33}
根据小节2.1,可知这里的consumer绑定的是Rasterizer::DoDraw(),接下里看看这个方法。
2.4 Rasterizer::DoDraw
[-> flutter/shell/common/rasterizer.cc]
1void Rasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) { 2 if (!layer_tree || !surface_) { 3 return; 4 } 5 //[见小节2.5] 6 if (DrawToSurface(*layer_tree)) { 7 //将layer tree记录到last_layer_tree_ 8 last_layer_tree_ = std::move(layer_tree); 9 } 10}
2.5 Rasterizer::DrawToSurface
[-> flutter/shell/common/rasterizer.cc]
1 bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) { 2 //此处的surface_为GPUSurfaceGL,得到的是SurfaceFrame [见小节2.6] 3 auto frame = surface_->AcquireFrame(layer_tree.frame_size()); 4 5 if (frame == nullptr) { 6 return false; 7 } 8 9 //将ui线程生成layer tree所花费时间,记录到合成器上下文的engine_time里 10 compositor_context_->engine_time().SetLapTime(layer_tree.construction_time()); 11 //获取SkCanvas指针 12 auto* canvas = frame->SkiaCanvas(); 13 14 auto* external_view_embedder = surface_->GetExternalViewEmbedder(); 15 16 if (external_view_embedder != nullptr) { 17 external_view_embedder->BeginFrame(layer_tree.frame_size()); 18 } 19 //返回的是ScopedFrame,[见小节2.7] 20 auto compositor_frame = compositor_context_->AcquireFrame( 21 surface_->GetContext(), canvas, external_view_embedder, 22 surface_->GetRootTransformation(), true); 23 24 if (canvas) { 25 canvas->clear(SK_ColorTRANSPARENT); 26 } 27 28 // [见小节2.8] 29 if (compositor_frame && compositor_frame->Raster(layer_tree, false)) { 30 //[见小节2.9] 31 frame->Submit(); 32 if (external_view_embedder != nullptr) { 33 external_view_embedder->SubmitFrame(surface_->GetContext()); 34 } 35 FireNextFrameCallbackIfPresent(); 36 37 if (surface_->GetContext()) 38 surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration); 39 40 return true; 41 } 42 43 return false; 44}
该方法主要功能:
- 执行AndroidSurface的AcquireFrame()来获取SurfaceFrame,此处AndroidSurface为GPUSurfaceGL子类;
- layer_tree.construction_time()记录ui线程生成layer tree所花费时间,将其记录到compositor_context_的engine_time,用于计算fps;
- 执行CompositorContext的AcquireFrame()来获取ScopedFrame;
- 执行ScopedFrame的Raster()进行绘制操作;
- 执行SurfaceFrame的Submit()来进行flush和SwapBuffers操作。
2.6 AndroidSurface::AcquireFrame
要知道surface_到底是怎么来的,先来看看AndroidSurface::Create()过程。
2.6.1 PlatformView::NotifyCreated
[-> flutter/shell/common/platform_view.h]
1void PlatformView::NotifyCreated() { 2 delegate_.OnPlatformViewCreated(CreateRenderingSurface()); //[见小节2.6.2] 3}
OnPlatformViewCreated()过程会通过rasterizer->Setup(std::move(surface))来初始化surface_变量,而surface_便是由CreateRenderingSurface()方法赋值初始化的,如下所示。
2.6.2 PlatformViewAndroid::CreateRenderingSurface
[-> flutter/shell/platform/android/platform_view_android.cc]
1std::unique_ptr<Surface> PlatformViewAndroid::CreateRenderingSurface() { 2 if (!android_surface_) { 3 return nullptr; 4 } 5 //[见小节2.6.3/ 2.6.4] 6 return android_surface_->CreateGPUSurface(); 7}
这里有两点需要关注一下:
- android_surface_变量:通过AndroidSurface::Create完成赋值初始化,返回的数据类型为AndroidSurfaceGL,见小节2.6.3;
- CreateGPUSurface():该方法返回的数据类型为GPUSurfaceGL,见小节2.6.4;
2.6.3 AndroidSurface::Create
[-> flutter/shell/platform/android/android_surface.cc]
1std::unique_ptr<AndroidSurface> AndroidSurface::Create( 2 bool use_software_rendering) { 3 if (use_software_rendering) { 4 auto software_surface = std::make_unique<AndroidSurfaceSoftware>(); 5 return software_surface->IsValid() ? std::move(software_surface) : nullptr; 6 } 7#if SHELL_ENABLE_VULKAN 8 auto vulkan_surface = std::make_unique<AndroidSurfaceVulkan;>(); 9 return vulkan_surface->IsValid() ? std::move(vulkan_surface) : nullptr; 10#else 11 auto gl_surface = std::make_unique<AndroidSurfaceGL>(); 12 return gl_surface->IsOffscreenContextValid() ? std::move(gl_surface) 13 : nullptr; 14#endif 15}
三种不同的AndroidSurface,目前android_surface_默认数据类型为AndroidSurfaceGL。
2.6.4 AndroidSurfaceGL::CreateGPUSurface
[-> flutter/shell/platform/android/android_surface_gl.cc]
1std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface() { 2 auto surface = std::make_unique<GPUSurfaceGL>(this); 3 return surface->IsValid() ? std::move(surface) : nullptr; 4}
可见surface_的类型为GPUSurfaceGL。再来看看看AcquireFrame()过程。
2.6.5 GPUSurfaceGL::AcquireFrame
[-> flutter/shell/gpu/gpu_surface_gl.cc]
1std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) { 2 ... 3 //此处delegate_是AndroidSurfaceGL,将其onscreen_context_设置为current 4 if (!delegate_->GLContextMakeCurrent()) { 5 return nullptr; 6 } 7 8 const auto root_surface_transformation = GetRootTransformation(); 9 10 sk_sp<SkSurface> surface = 11 AcquireRenderSurface(size, root_surface_transformation); 12 13 if (surface == nullptr) { 14 return nullptr; 15 } 16 17 surface->getCanvas()->setMatrix(root_surface_transformation); 18 19 SurfaceFrame::SubmitCallback submit_callback = 20 [weak = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame, 21 SkCanvas* canvas) { 22 return weak ? weak->PresentSurface(canvas) : false; 23 }; 24 25 //创建SurfaceFrame指针 26 return std::make_unique<SurfaceFrame>(surface, submit_callback); 27}
该过程会创建SurfaceFrame并设置SubmitCallback方法()。
2.7 CompositorContext::AcquireFrame
[-> flutter/flow/compositor_context.cc]
1std::unique_ptr<CompositorContext::ScopedFrame> CompositorContext::AcquireFrame( 2 GrContext* gr_context, 3 SkCanvas* canvas, 4 ExternalViewEmbedder* view_embedder, 5 const SkMatrix& root_surface_transformation, 6 bool instrumentation_enabled) { 7 //创建ScopedFrame指针 8 return std::make_unique<ScopedFrame>(*this, gr_context, canvas, view_embedder, 9 root_surface_transformation, 10 instrumentation_enabled); 11}
创建ScopedFrame,其成遍历context_记录着CompositorContext,而CompositorContext是在Rasterizer对象初始化的时候创建的。
2.8 ScopedFrame::Raster
[-> flutter/flow/compositor_context.cc]
1bool CompositorContext::ScopedFrame::Raster(flow::LayerTree& layer_tree, 2 bool ignore_raster_cache) { 3 layer_tree.Preroll(*this, ignore_raster_cache); 4 layer_tree.Paint(*this, ignore_raster_cache); 5 return true; 6}
从小节2.5可知ignore_raster_cache等于false,会采用raster缓存。
2.9 LayerTree::Preroll
[-> flutter/flow/layers/layer_tree.cc]
1void LayerTree::Preroll(CompositorContext::ScopedFrame& frame, 2 bool ignore_raster_cache) { 3 TRACE_EVENT0("flutter", "LayerTree::Preroll"); 4 SkColorSpace* color_space = 5 frame.canvas() ? frame.canvas()->imageInfo().colorSpace() : nullptr; 6 frame.context().raster_cache().SetCheckboardCacheImages( 7 checkerboard_raster_cache_images_); 8 PrerollContext context = { 9 //此处采用raster缓存 10 ignore_raster_cache ? nullptr : &frame.context().raster_cache(), 11 frame.gr_context(), 12 frame.view_embedder(), 13 color_space, 14 kGiantRect, 15 frame.context().frame_time(), 16 frame.context().engine_time(), 17 frame.context().texture_registry(), 18 checkerboard_offscreen_layers_}; 19 //执行相应layer子类的preroll方法 20 root_layer_->Preroll(&context, frame.root_surface_transformation()); 21}
该方法主要功能:
- frame是由小节2.7过程赋值,其类型为ScopedFrame;
- 用于统计fps的frame_time和engine_time是来自于CompositorContext的成员;
- 从root_layer_记录图层树的根节点,根据根节点的具体ContainerLayer子类类型来执行相应类的Preroll方法(), 这里以ContainerLayer为例子来说明。
2.9.1 ContainerLayer::Preroll
[-> flutter/flow/layers/container_layer.cc]
1void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { 2 TRACE_EVENT0("flutter", "ContainerLayer::Preroll"); 3 4 SkRect child_paint_bounds = SkRect::MakeEmpty(); 5 //[见小节2.9.2] 6 PrerollChildren(context, matrix, &child_paint_bounds); 7 //设置绘制范围 8 set_paint_bounds(child_paint_bounds); 9}
该方法主要功能是遍历所有子图层,执行具体图层的Preroll()方法,并设置绘制范围。
2.9.2 ContainerLayer::PrerollChildren
[-> flutter/flow/layers/container_layer.cc]
1void ContainerLayer::PrerollChildren(PrerollContext* context, 2 const SkMatrix& child_matrix, 3 SkRect* child_paint_bounds) { 4 for (auto& layer : layers_) { 5 PrerollContext child_context = *context; 6 //遍历所有的图层,依次执行preroll 7 layer->Preroll(&child_context, child_matrix); 8 //根据需要设置是否需要合成 9 if (layer->needs_system_composite()) { 10 set_needs_system_composite(true); 11 } 12 child_paint_bounds->join(layer->paint_bounds()); 13 } 14}
2.10 LayerTree::Paint
[-> flutter/flow/layers/layer_tree.cc]
1void LayerTree::Paint(CompositorContext::ScopedFrame& frame, 2 bool ignore_raster_cache) const { 3 TRACE_EVENT0("flutter", "LayerTree::Paint"); 4 SkISize canvas_size = frame.canvas()->getBaseLayerSize(); 5 SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height()); 6 internal_nodes_canvas.addCanvas(frame.canvas()); 7 if (frame.view_embedder() != nullptr) { 8 auto overlay_canvases = frame.view_embedder()->GetCurrentCanvases(); 9 for (size_t i = 0; i < overlay_canvases.size(); i++) { 10 internal_nodes_canvas.addCanvas(overlay_canvases[i]); 11 } 12 } 13 14 Layer::PaintContext context = { 15 (SkCanvas*)&internal_nodes_canvas, 16 frame.canvas(), 17 frame.gr_context(), 18 frame.view_embedder(), 19 frame.context().frame_time(), 20 frame.context().engine_time(), 21 frame.context().texture_registry(), 22 ignore_raster_cache ? nullptr : &frame.context().raster_cache(), 23 checkerboard_offscreen_layers_}; 24 //当paint_bounds_不为空则需要绘制 25 if (root_layer_->needs_painting()) 26 root_layer_->Paint(context); 27}
paint_bounds_是在Preroll过程调用set_paint_bounds方法来赋值的,当paint_bounds_不为空则需要绘制。
对于Paint绘制过程,调用哪个方法取决于图层树结构中相应的layer类型,详见Layer类图 。每个执行Paint()过程会再调用PaintChildren来遍历layers_的子图层,下面列举图上几个类的Paint绘制方法。
2.10.1 TransformLayer::Paint
[-> flutter/flow/layers/transform_layer.cc]
1void TransformLayer::Paint(PaintContext& context) const { 2 TRACE_EVENT0("flutter", "TransformLayer::Paint"); 3 FML_DCHECK(needs_painting()); 4 5 SkAutoCanvasRestore save(context.internal_nodes_canvas, true); 6 context.internal_nodes_canvas->concat(transform_); 7 PaintChildren(context); 8}
2.10.2 PhysicalShapeLayer::Paint
[-> flutter/flow/layers/physical_shape_layer.cc]
1void PhysicalShapeLayer::Paint(PaintContext& context) const { 2 TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint"); 3 FML_DCHECK(needs_painting()); 4 5 if (elevation_ != 0) { 6 DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_, 7 SkColorGetA(color_) != 0xff, device_pixel_ratio_); 8 } 9 10 SkPaint paint; 11 paint.setColor(color_); 12 if (clip_behavior_ != Clip::antiAliasWithSaveLayer) { 13 context.leaf_nodes_canvas->drawPath(path_, paint); 14 } 15 16 int saveCount = context.internal_nodes_canvas->save(); 17 switch (clip_behavior_) { 18 case Clip::hardEdge: 19 context.internal_nodes_canvas->clipPath(path_, false); 20 break; 21 case Clip::antiAlias: 22 context.internal_nodes_canvas->clipPath(path_, true); 23 break; 24 case Clip::antiAliasWithSaveLayer: 25 context.internal_nodes_canvas->clipPath(path_, true); 26 context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); 27 break; 28 case Clip::none: 29 break; 30 } 31 32 if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { 33 context.leaf_nodes_canvas->drawPaint(paint); 34 } 35 36 PaintChildren(context); 37 38 context.internal_nodes_canvas->restoreToCount(saveCount); 39}
2.10.3 ClipRectLayer::Paint
[-> flutter/flow/layers/clip_rect_layer.cc]
1void ClipRectLayer::Paint(PaintContext& context) const { 2 TRACE_EVENT0("flutter", "ClipRectLayer::Paint"); 3 FML_DCHECK(needs_painting()); 4 5 SkAutoCanvasRestore save(context.internal_nodes_canvas, true); 6 context.internal_nodes_canvas->clipRect(paint_bounds(), 7 clip_behavior_ != Clip::hardEdge); 8 if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { 9 context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); 10 } 11 PaintChildren(context); 12 if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { 13 context.internal_nodes_canvas->restore(); 14 } 15}
2.10.4 PictureLayer::Paint
[-> flutter/flow/layers/picture_layer.cc]
1void PictureLayer::Paint(PaintContext& context) const { 2 TRACE_EVENT0("flutter", "PictureLayer::Paint"); 3 FML_DCHECK(picture_.get()); 4 FML_DCHECK(needs_painting()); 5 6 SkAutoCanvasRestore save(context.leaf_nodes_canvas, true); 7 context.leaf_nodes_canvas->translate(offset_.x(), offset_.y()); 8#ifndef SUPPORT_FRACTIONAL_TRANSLATION 9 context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM( 10 context.leaf_nodes_canvas->getTotalMatrix())); 11#endif 12 13 if (context.raster_cache) { 14 const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); 15 RasterCacheResult result = context.raster_cache->Get(*picture(), ctm); 16 if (result.is_valid()) { 17 result.draw(*context.leaf_nodes_canvas); 18 return; 19 } 20 } 21 context.leaf_nodes_canvas->drawPicture(picture()); 22}
2.10.5 OpacityLayer::Paint
[-> flutter/flow/layers/opacity_layer.cc]
1void OpacityLayer::Paint(PaintContext& context) const { 2 TRACE_EVENT0("flutter", "OpacityLayer::Paint"); 3 4 SkPaint paint; 5 paint.setAlpha(alpha_); 6 7 SkAutoCanvasRestore save(context.internal_nodes_canvas, true); 8 context.internal_nodes_canvas->translate(offset_.fX, offset_.fY); 9 10 if (context.view_embedder == nullptr && layers().size() == 1 && 11 context.raster_cache) { 12 const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); 13 RasterCacheResult child_cache = 14 context.raster_cache->Get(layers()[0].get(), ctm); 15 if (child_cache.is_valid()) { 16 child_cache.draw(*context.leaf_nodes_canvas, &paint); 17 return; 18 } 19 } 20 21 SkRect saveLayerBounds; 22 paint_bounds() 23 .makeOffset(-offset_.fX, -offset_.fY) 24 .roundOut(&saveLayerBounds); 25 26 Layer::AutoSaveLayer save_layer = 27 Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint); 28 PaintChildren(context); 29}
2.11 SurfaceFrame::Submit
[-> flutter/shell/common/surface.cc]
1bool SurfaceFrame::Submit() { 2 if (submitted_) { 3 return false; 4 } 5 submitted_ = PerformSubmit(); //[见小节2.11.1] 6 return submitted_; 7}
再回到小节2.5,执行完Raster()后需要执行Submit()提交。
2.11.1 SurfaceFrame::PerformSubmit
[-> flutter/shell/common/surface.cc]
1bool SurfaceFrame::PerformSubmit() { 2 if (submit_callback_ == nullptr) { 3 return false; 4 } 5 //[见小节2.11.2] 6 if (submit_callback_(*this, SkiaCanvas())) { 7 return true; 8 } 9 10 return false; 11}
此处的submit_callback_是由[小节2.6.4]中赋值的,对应的方法是PresentSurface()
2.11.2 GPUSurfaceGL::PresentSurface
[-> flutter/shell/gpu/gpu_surface_gl.cc]
1bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) { 2 if (delegate_ == nullptr || canvas == nullptr || context_ == nullptr) { 3 return false; 4 } 5 6 if (offscreen_surface_ != nullptr) { 7 TRACE_EVENT0("flutter", "CopyTextureOnscreen"); 8 SkPaint paint; 9 SkCanvas* onscreen_canvas = onscreen_surface_->getCanvas(); 10 onscreen_canvas->clear(SK_ColorTRANSPARENT); 11 onscreen_canvas->drawImage(offscreen_surface_->makeImageSnapshot(), 0, 0, 12 &paint); 13 } 14 15 { 16 TRACE_EVENT0("flutter", "SkCanvas::Flush"); 17 //获取SkSurface的fCachedCanvas,再调用其flush(),[见小节2.12] 18 onscreen_surface_->getCanvas()->flush(); 19 } 20 21 if (!delegate_->GLContextPresent()) { //[见小节2.13] 22 return false; 23 } 24 25 if (delegate_->GLContextFBOResetAfterPresent()) { 26 auto current_size = 27 SkISize::Make(onscreen_surface_->width(), onscreen_surface_->height()); 28 29 auto new_onscreen_surface = 30 WrapOnscreenSurface(context_.get(), // GL context 31 current_size, // root surface size 32 delegate_->GLContextFBO() // window FBO ID 33 ); 34 35 if (!new_onscreen_surface) { 36 return false; 37 } 38 onscreen_surface_ = std::move(new_onscreen_surface); 39 } 40 return true; 41}
此处delegate_为AndroidSurfaceGL类型。
2.12 SkCanvas::flush
[-> third_party/skia/src/core/SkCanvas.cpp]
1void SkCanvas::flush() { 2 this->onFlush(); 3}
2.12.1 SkCanvas::onFlush
[-> third_party/skia/src/core/SkCanvas.cpp]
1void SkCanvas::onFlush() { 2 SkBaseDevice* device = this->getDevice(); 3 if (device) { 4 device->flush(); 5 } 6}
2.13 AndroidSurfaceGL::GLContextPresent
[-> flutter/shell/platform/android/android_context_gl.cc]
1bool AndroidSurfaceGL::GLContextPresent() { 2 return onscreen_context_->SwapBuffers(); 3}
2.13.1 AndroidContextGL::SwapBuffers
[-> flutter/shell/platform/android/android_context_gl.cc]
1bool AndroidContextGL::SwapBuffers() { 2 TRACE_EVENT0("flutter", "AndroidContextGL::SwapBuffers"); 3 return eglSwapBuffers(environment_->Display(), surface_); 4}
附录
本文涉及到相关源码文件
1flutter/shell/common/ 2 - shell.cc 3 - rasterizer.cc 4 - surface.cc 5 - platform_view.h 6 7flutter/shell/platform/android/ 8 - platform_view_android.cc 9 - android_surface.cc 10 - android_surface_gl.cc 11 - android_context_gl.cc 12 13flutter/flow/layers/ 14 - layer_tree.cc 15 - container_layer.cc 16 - transform_layer.cc 17 - physical_shape_layer.cc 18 - clip_rect_layer.cc 19 - picture_layer.cc 20 21flutter/fml/message_loop_impl.cc 22flutter/synchronization/pipeline.h 23flutter/flow/compositor_context.cc 24flutter/shell/gpu/gpu_surface_gl.cc 25third_party/skia/src/core/SkCanvas.cpp
本文转自 http://gityuan.com/2019/06/16/flutter_gpu_draw/,如有侵权,请联系删除。
