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.
This commit is contained in:
Adam Barth
2016-04-28 10:15:38 -07:00
parent 1b3ef50223
commit 73790140e7
4 changed files with 46 additions and 83 deletions

View File

@@ -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<SkPicture> 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() {

View File

@@ -8,66 +8,46 @@
#include <memory>
#include <string>
#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<SkPicture> 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);
};

View File

@@ -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,

View File

@@ -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; }