From 73790140e751ebc4dd57802a63e06bd694fc97a3 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 28 Apr 2016 10:15:38 -0700 Subject: [PATCH] Record layer tree to an SkPicture before rasterization (flutter/engine#2628) This lets Skia run an optimization pass over the SkPicture before actually issuing GL commands. --- engine/src/flutter/flow/compositor_context.cc | 58 ++++++++++--------- engine/src/flutter/flow/compositor_context.h | 46 +++++---------- engine/src/flutter/flow/layers/layer_tree.cc | 22 +------ engine/src/flutter/flow/layers/layer_tree.h | 3 +- 4 files changed, 46 insertions(+), 83 deletions(-) diff --git a/engine/src/flutter/flow/compositor_context.cc b/engine/src/flutter/flow/compositor_context.cc index 5dbc25f795..b2872b9aaa 100644 --- a/engine/src/flutter/flow/compositor_context.cc +++ b/engine/src/flutter/flow/compositor_context.cc @@ -5,7 +5,10 @@ #include "flow/compositor_context.h" #include "base/logging.h" +#include "base/trace_event/trace_event.h" +#include "flow/layers/layer_tree.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" namespace flow { @@ -15,40 +18,39 @@ CompositorContext::CompositorContext() { CompositorContext::~CompositorContext() { } -void CompositorContext::BeginFrame(ScopedFrame& frame, - bool enable_instrumentation) { - if (enable_instrumentation) { - frame_count_.Increment(); - frame_time_.Start(); - } +void CompositorContext::Preroll(GrContext* gr_context, LayerTree* layer_tree) { + TRACE_EVENT0("flutter", "CompositorContext::Preroll"); + engine_time_.SetLapTime(layer_tree->construction_time()); + Layer::PrerollContext context = { + raster_cache_, + gr_context, + SkRect::MakeEmpty(), + }; + layer_tree->root_layer()->Preroll(&context, SkMatrix()); } -void CompositorContext::EndFrame(ScopedFrame& frame, - bool enable_instrumentation) { - raster_cache_.SweepAfterFrame(); - if (enable_instrumentation) { - frame_time_.Stop(); - } +sk_sp CompositorContext::Record(const SkRect& bounds, Layer* layer) { + TRACE_EVENT0("flutter", "CompositorContext::Record"); + SkRTreeFactory rtree_factory; + uint32_t flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag; + SkPictureRecorder recorder; + Layer::PaintContext paint_context{ + *recorder.beginRecording(bounds, &rtree_factory, flags), + frame_time_, + engine_time_, + }; + layer->Paint(paint_context); + return recorder.finishRecordingAsPicture(); } -CompositorContext::ScopedFrame CompositorContext::AcquireFrame( - GrContext* gr_context, SkCanvas& canvas, bool instrumentation_enabled) { - return ScopedFrame(*this, gr_context, canvas, instrumentation_enabled); +CompositorContext::Scope::Scope(CompositorContext& context) + : context_(context) { + context_.frame_time_.Start(); } -CompositorContext::ScopedFrame::ScopedFrame(CompositorContext& context, - GrContext* gr_context, - SkCanvas& canvas, - bool instrumentation_enabled) - : context_(context), gr_context_(gr_context), canvas_(&canvas), - instrumentation_enabled_(instrumentation_enabled) { - context_.BeginFrame(*this, instrumentation_enabled_); -} - -CompositorContext::ScopedFrame::ScopedFrame(ScopedFrame&& frame) = default; - -CompositorContext::ScopedFrame::~ScopedFrame() { - context_.EndFrame(*this, instrumentation_enabled_); +CompositorContext::Scope::~Scope() { + context_.raster_cache_.SweepAfterFrame(); + context_.frame_time_.Stop(); } void CompositorContext::OnGrContextDestroyed() { diff --git a/engine/src/flutter/flow/compositor_context.h b/engine/src/flutter/flow/compositor_context.h index 4ac7d51745..3df3617b9a 100644 --- a/engine/src/flutter/flow/compositor_context.h +++ b/engine/src/flutter/flow/compositor_context.h @@ -8,66 +8,46 @@ #include #include -#include "base/macros.h" #include "base/logging.h" +#include "base/macros.h" #include "flow/instrumentation.h" #include "flow/raster_cache.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/gpu/GrContext.h" namespace flow { +class Layer; +class LayerTree; class CompositorContext { public: - class ScopedFrame { + class Scope { public: - SkCanvas& canvas() { return *canvas_; } - CompositorContext& context() const { return context_; } - GrContext* gr_context() const { return gr_context_; } - - ScopedFrame(ScopedFrame&& frame); - ~ScopedFrame(); + explicit Scope(CompositorContext& context); + ~Scope(); private: CompositorContext& context_; - GrContext* gr_context_; - SkCanvas* canvas_; - const bool instrumentation_enabled_; - ScopedFrame(CompositorContext& context, - GrContext* gr_context, - SkCanvas& canvas, - bool instrumentation_enabled); - - friend class CompositorContext; - - DISALLOW_COPY_AND_ASSIGN(ScopedFrame); + DISALLOW_COPY_AND_ASSIGN(Scope); }; CompositorContext(); ~CompositorContext(); - ScopedFrame AcquireFrame(GrContext* gr_context, - SkCanvas& canvas, - bool instrumentation_enabled = true); + void Preroll(GrContext* gr_context, LayerTree* layer_tree); + sk_sp Record(const SkRect& bounds, Layer* layer); void OnGrContextDestroyed(); - RasterCache& raster_cache() { return raster_cache_; } - const Counter& frame_count() const { return frame_count_; } - const Stopwatch& frame_time() const { return frame_time_; } - Stopwatch& engine_time() { return engine_time_; }; + const Stopwatch& frame_time() { return frame_time_; } private: RasterCache raster_cache_; - - Counter frame_count_; Stopwatch frame_time_; Stopwatch engine_time_; - void BeginFrame(ScopedFrame& frame, bool enable_instrumentation); - void EndFrame(ScopedFrame& frame, bool enable_instrumentation); - DISALLOW_COPY_AND_ASSIGN(CompositorContext); }; diff --git a/engine/src/flutter/flow/layers/layer_tree.cc b/engine/src/flutter/flow/layers/layer_tree.cc index 0d4e58b971..c3cac5179c 100644 --- a/engine/src/flutter/flow/layers/layer_tree.cc +++ b/engine/src/flutter/flow/layers/layer_tree.cc @@ -15,26 +15,8 @@ LayerTree::LayerTree() : scene_version_(0), rasterizer_tracing_threshold_(0) { LayerTree::~LayerTree() { } -void LayerTree::Raster(CompositorContext::ScopedFrame& frame) { - { - TRACE_EVENT0("flutter", "LayerTree::Preroll"); - Layer::PrerollContext context = { - frame.context().raster_cache(), - frame.gr_context(), - SkRect::MakeEmpty(), - }; - root_layer_->Preroll(&context, SkMatrix()); - } - - { - Layer::PaintContext context = { - frame.canvas(), - frame.context().frame_time(), - frame.context().engine_time(), - }; - TRACE_EVENT0("flutter", "LayerTree::Paint"); - root_layer_->Paint(context); - } +SkRect LayerTree::GetBounds() const { + return SkRect::MakeWH(frame_size_.width(), frame_size_.height()); } void LayerTree::UpdateScene(mojo::gfx::composition::SceneUpdate* update, diff --git a/engine/src/flutter/flow/layers/layer_tree.h b/engine/src/flutter/flow/layers/layer_tree.h index ef83ce6abb..349ed5649f 100644 --- a/engine/src/flutter/flow/layers/layer_tree.h +++ b/engine/src/flutter/flow/layers/layer_tree.h @@ -21,8 +21,6 @@ class LayerTree { LayerTree(); ~LayerTree(); - void Raster(CompositorContext::ScopedFrame& frame); - // TODO(abarth): Integrate scene updates with the rasterization pass so that // we can draw on top of child scenes (and so that we can apply clips and // blending operations to child scene). @@ -35,6 +33,7 @@ class LayerTree { root_layer_ = std::move(root_layer); } + SkRect GetBounds() const; const SkISize& frame_size() const { return frame_size_; } void set_frame_size(const SkISize& frame_size) { frame_size_ = frame_size; }