mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #2258 from abarth/flow
Move //sky/compositor to //flow
This commit is contained in:
commit
4742f4ef6a
45
engine/src/flutter/flow/BUILD.gn
Normal file
45
engine/src/flutter/flow/BUILD.gn
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
source_set("flow") {
|
||||
sources = [
|
||||
"checkerboard.cc",
|
||||
"checkerboard.h",
|
||||
"clip_path_layer.cc",
|
||||
"clip_path_layer.h",
|
||||
"clip_rect_layer.cc",
|
||||
"clip_rect_layer.h",
|
||||
"clip_rrect_layer.cc",
|
||||
"clip_rrect_layer.h",
|
||||
"color_filter_layer.cc",
|
||||
"color_filter_layer.h",
|
||||
"container_layer.cc",
|
||||
"container_layer.h",
|
||||
"instrumentation.cc",
|
||||
"instrumentation.h",
|
||||
"layer.cc",
|
||||
"layer.h",
|
||||
"layer_tree.cc",
|
||||
"layer_tree.h",
|
||||
"opacity_layer.cc",
|
||||
"opacity_layer.h",
|
||||
"paint_context.cc",
|
||||
"paint_context.h",
|
||||
"picture_layer.cc",
|
||||
"picture_layer.h",
|
||||
"raster_cache.cc",
|
||||
"raster_cache.h",
|
||||
"performance_overlay_layer.cc",
|
||||
"performance_overlay_layer.h",
|
||||
"shader_mask_layer.cc",
|
||||
"shader_mask_layer.h",
|
||||
"transform_layer.cc",
|
||||
"transform_layer.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//skia",
|
||||
]
|
||||
}
|
||||
6
engine/src/flutter/flow/README.md
Normal file
6
engine/src/flutter/flow/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
Flow
|
||||
====
|
||||
|
||||
Flow is a simple compositor based on Skia that the Flutter engine uses to cache
|
||||
recoded paint commands and pixels generated from those recordings. Flow runs on
|
||||
the GPU thread and uploads information to the GPU.
|
||||
45
engine/src/flutter/flow/checkerboard.cc
Normal file
45
engine/src/flutter/flow/checkerboard.cc
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/checkerboard.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkShader.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
static SkShader* CreateCheckerboardShader(SkColor c1, SkColor c2, int size) {
|
||||
SkBitmap bm;
|
||||
bm.allocN32Pixels(2 * size, 2 * size);
|
||||
bm.eraseColor(c1);
|
||||
bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
|
||||
bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
|
||||
return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
|
||||
SkShader::kRepeat_TileMode);
|
||||
}
|
||||
|
||||
static void DrawCheckerboard(SkCanvas* canvas,
|
||||
SkColor c1,
|
||||
SkColor c2,
|
||||
int size) {
|
||||
SkPaint paint;
|
||||
paint.setShader(CreateCheckerboardShader(c1, c2, size))->unref();
|
||||
canvas->drawPaint(paint);
|
||||
}
|
||||
|
||||
void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect) {
|
||||
// Draw a checkerboard
|
||||
canvas->save();
|
||||
canvas->clipRect(rect);
|
||||
DrawCheckerboard(canvas, 0x4400FF00, 0x00000000, 12);
|
||||
canvas->restore();
|
||||
|
||||
// Stroke the drawn area
|
||||
SkPaint debugPaint;
|
||||
debugPaint.setStrokeWidth(3);
|
||||
debugPaint.setColor(SK_ColorRED);
|
||||
debugPaint.setStyle(SkPaint::kStroke_Style);
|
||||
canvas->drawRect(rect, debugPaint);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
16
engine/src/flutter/flow/checkerboard.h
Normal file
16
engine/src/flutter/flow/checkerboard.h
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_CHECKERBOARD_H_
|
||||
#define FLOW_CHECKERBOARD_H_
|
||||
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect);
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_CHECKERBOARD_H_
|
||||
23
engine/src/flutter/flow/clip_path_layer.cc
Normal file
23
engine/src/flutter/flow/clip_path_layer.cc
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/clip_path_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ClipPathLayer::ClipPathLayer() {
|
||||
}
|
||||
|
||||
ClipPathLayer::~ClipPathLayer() {
|
||||
}
|
||||
|
||||
void ClipPathLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, false);
|
||||
canvas.saveLayer(&clip_path_.getBounds(), nullptr);
|
||||
canvas.clipPath(clip_path_);
|
||||
PaintChildren(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
30
engine/src/flutter/flow/clip_path_layer.h
Normal file
30
engine/src/flutter/flow/clip_path_layer.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_CLIP_PATH_LAYER_H_
|
||||
#define FLOW_CLIP_PATH_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ClipPathLayer : public ContainerLayer {
|
||||
public:
|
||||
ClipPathLayer();
|
||||
~ClipPathLayer() override;
|
||||
|
||||
void set_clip_path(const SkPath& clip_path) { clip_path_ = clip_path; }
|
||||
|
||||
protected:
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
SkPath clip_path_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClipPathLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_CLIP_PATH_LAYER_H_
|
||||
22
engine/src/flutter/flow/clip_rect_layer.cc
Normal file
22
engine/src/flutter/flow/clip_rect_layer.cc
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/clip_rect_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ClipRectLayer::ClipRectLayer() {
|
||||
}
|
||||
|
||||
ClipRectLayer::~ClipRectLayer() {
|
||||
}
|
||||
|
||||
void ClipRectLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, true);
|
||||
canvas.clipRect(clip_rect_);
|
||||
PaintChildren(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
30
engine/src/flutter/flow/clip_rect_layer.h
Normal file
30
engine/src/flutter/flow/clip_rect_layer.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_CLIP_RECT_LAYER_H_
|
||||
#define FLOW_CLIP_RECT_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ClipRectLayer : public ContainerLayer {
|
||||
public:
|
||||
ClipRectLayer();
|
||||
~ClipRectLayer() override;
|
||||
|
||||
void set_clip_rect(const SkRect& clip_rect) { clip_rect_ = clip_rect; }
|
||||
|
||||
protected:
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
SkRect clip_rect_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClipRectLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_CLIP_RECT_LAYER_H_
|
||||
23
engine/src/flutter/flow/clip_rrect_layer.cc
Normal file
23
engine/src/flutter/flow/clip_rrect_layer.cc
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/clip_rrect_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ClipRRectLayer::ClipRRectLayer() {
|
||||
}
|
||||
|
||||
ClipRRectLayer::~ClipRRectLayer() {
|
||||
}
|
||||
|
||||
void ClipRRectLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, false);
|
||||
canvas.saveLayer(&clip_rrect_.getBounds(), nullptr);
|
||||
canvas.clipRRect(clip_rrect_);
|
||||
PaintChildren(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
29
engine/src/flutter/flow/clip_rrect_layer.h
Normal file
29
engine/src/flutter/flow/clip_rrect_layer.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_CLIP_RRECT_LAYER_H_
|
||||
#define FLOW_CLIP_RRECT_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ClipRRectLayer : public ContainerLayer {
|
||||
public:
|
||||
ClipRRectLayer();
|
||||
~ClipRRectLayer() override;
|
||||
|
||||
void set_clip_rrect(const SkRRect& clip_rrect) { clip_rrect_ = clip_rrect; }
|
||||
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
SkRRect clip_rrect_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClipRRectLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_CLIP_RRECT_LAYER_H_
|
||||
32
engine/src/flutter/flow/color_filter_layer.cc
Normal file
32
engine/src/flutter/flow/color_filter_layer.cc
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/color_filter_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ColorFilterLayer::ColorFilterLayer() {
|
||||
}
|
||||
|
||||
ColorFilterLayer::~ColorFilterLayer() {
|
||||
}
|
||||
|
||||
void ColorFilterLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
set_paint_bounds(context->child_paint_bounds);
|
||||
}
|
||||
|
||||
void ColorFilterLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
skia::RefPtr<SkColorFilter> color_filter =
|
||||
skia::AdoptRef(SkColorFilter::CreateModeFilter(color_, transfer_mode_));
|
||||
SkPaint paint;
|
||||
paint.setColorFilter(color_filter.get());
|
||||
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, false);
|
||||
canvas.saveLayer(&paint_bounds(), &paint);
|
||||
PaintChildren(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
36
engine/src/flutter/flow/color_filter_layer.h
Normal file
36
engine/src/flutter/flow/color_filter_layer.h
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_COLOR_FILTER_LAYER_H_
|
||||
#define FLOW_COLOR_FILTER_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ColorFilterLayer : public ContainerLayer {
|
||||
public:
|
||||
ColorFilterLayer();
|
||||
~ColorFilterLayer() override;
|
||||
|
||||
void set_color(SkColor color) { color_ = color; }
|
||||
|
||||
void set_transfer_mode(SkXfermode::Mode transfer_mode) {
|
||||
transfer_mode_ = transfer_mode;
|
||||
}
|
||||
|
||||
protected:
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
SkXfermode::Mode transfer_mode_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ColorFilterLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_COLOR_FILTER_LAYER_H_
|
||||
40
engine/src/flutter/flow/container_layer.cc
Normal file
40
engine/src/flutter/flow/container_layer.cc
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ContainerLayer::ContainerLayer() {
|
||||
}
|
||||
|
||||
ContainerLayer::~ContainerLayer() {
|
||||
}
|
||||
|
||||
void ContainerLayer::Add(std::unique_ptr<Layer> layer) {
|
||||
layer->set_parent(this);
|
||||
layers_.push_back(std::move(layer));
|
||||
}
|
||||
|
||||
void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
PrerollChildren(context, matrix);
|
||||
}
|
||||
|
||||
void ContainerLayer::PrerollChildren(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
SkRect child_paint_bounds;
|
||||
for (auto& layer : layers_) {
|
||||
PrerollContext child_context = *context;
|
||||
layer->Preroll(&child_context, matrix);
|
||||
child_paint_bounds.join(child_context.child_paint_bounds);
|
||||
}
|
||||
context->child_paint_bounds = child_paint_bounds;
|
||||
}
|
||||
|
||||
void ContainerLayer::PaintChildren(PaintContext::ScopedFrame& frame) const {
|
||||
for (auto& layer : layers_)
|
||||
layer->Paint(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
35
engine/src/flutter/flow/container_layer.h
Normal file
35
engine/src/flutter/flow/container_layer.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_CONTAINER_LAYER_H_
|
||||
#define FLOW_CONTAINER_LAYER_H_
|
||||
|
||||
#include <vector>
|
||||
#include "flow/layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ContainerLayer : public Layer {
|
||||
public:
|
||||
ContainerLayer();
|
||||
~ContainerLayer() override;
|
||||
|
||||
void Add(std::unique_ptr<Layer> layer);
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void PrerollChildren(PrerollContext* context, const SkMatrix& matrix);
|
||||
|
||||
void PaintChildren(PaintContext::ScopedFrame& frame) const;
|
||||
|
||||
const std::vector<std::unique_ptr<Layer>>& layers() const { return layers_; }
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Layer>> layers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ContainerLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_CONTAINER_LAYER_H_
|
||||
140
engine/src/flutter/flow/instrumentation.cc
Normal file
140
engine/src/flutter/flow/instrumentation.cc
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/instrumentation.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
|
||||
namespace flow {
|
||||
namespace instrumentation {
|
||||
|
||||
static const size_t kMaxSamples = 120;
|
||||
static const size_t kMaxFrameMarkers = 8;
|
||||
static const double kOneFrameMS = 1e3 / 60.0;
|
||||
|
||||
Stopwatch::Stopwatch() : _start(base::TimeTicks::Now()), _current_sample(0) {
|
||||
const base::TimeDelta delta;
|
||||
_laps.resize(kMaxSamples, delta);
|
||||
}
|
||||
|
||||
void Stopwatch::start() {
|
||||
_start = base::TimeTicks::Now();
|
||||
_current_sample = (_current_sample + 1) % kMaxSamples;
|
||||
}
|
||||
|
||||
void Stopwatch::stop() {
|
||||
_laps[_current_sample] = base::TimeTicks::Now() - _start;
|
||||
}
|
||||
|
||||
void Stopwatch::setLapTime(const base::TimeDelta& delta) {
|
||||
_current_sample = (_current_sample + 1) % kMaxSamples;
|
||||
_laps[_current_sample] = delta;
|
||||
}
|
||||
|
||||
const base::TimeDelta& Stopwatch::lastLap() const {
|
||||
return _laps[(_current_sample - 1) % kMaxSamples];
|
||||
}
|
||||
|
||||
static inline constexpr double UnitFrameInterval(double frameTimeMS) {
|
||||
return frameTimeMS * 60.0 * 1e-3;
|
||||
}
|
||||
|
||||
base::TimeDelta Stopwatch::maxDelta() const {
|
||||
base::TimeDelta maxDelta;
|
||||
for (size_t i = 0; i < kMaxSamples; i++) {
|
||||
if (_laps[i] > maxDelta) {
|
||||
maxDelta = _laps[i];
|
||||
}
|
||||
}
|
||||
return maxDelta;
|
||||
}
|
||||
|
||||
void Stopwatch::visualize(SkCanvas& canvas, const SkRect& rect) const {
|
||||
SkPaint paint;
|
||||
|
||||
// Paint the background
|
||||
paint.setColor(0xAAFFFFFF);
|
||||
canvas.drawRect(rect, paint);
|
||||
|
||||
// Paint the graph
|
||||
SkPath path;
|
||||
const SkScalar width = rect.width();
|
||||
const SkScalar height = rect.height();
|
||||
|
||||
// Find the max delta. We use this to scale the graph
|
||||
|
||||
double maxInterval = maxDelta().InMillisecondsF();
|
||||
|
||||
if (maxInterval < kOneFrameMS) {
|
||||
maxInterval = kOneFrameMS;
|
||||
} else {
|
||||
maxInterval =
|
||||
kOneFrameMS * (static_cast<size_t>(maxInterval / kOneFrameMS) + 1);
|
||||
}
|
||||
|
||||
const double maxUnitInterval = UnitFrameInterval(maxInterval);
|
||||
|
||||
// Draw the path
|
||||
double unitHeight =
|
||||
UnitFrameInterval(_laps[0].InMillisecondsF()) / maxUnitInterval;
|
||||
|
||||
path.moveTo(0, height);
|
||||
path.lineTo(0, height * (1.0 - unitHeight));
|
||||
|
||||
for (size_t i = 0; i < kMaxSamples; i++) {
|
||||
double unitWidth = (static_cast<double>(i + 1) / kMaxSamples);
|
||||
unitHeight =
|
||||
UnitFrameInterval(_laps[i].InMillisecondsF()) / maxUnitInterval;
|
||||
path.lineTo(width * unitWidth, height * (1.0 - unitHeight));
|
||||
}
|
||||
|
||||
path.lineTo(width, height);
|
||||
|
||||
path.close();
|
||||
|
||||
paint.setColor(0xAA0000FF);
|
||||
canvas.drawPath(path, paint);
|
||||
|
||||
paint.setStrokeWidth(1);
|
||||
paint.setStyle(SkPaint::Style::kStroke_Style);
|
||||
paint.setColor(0xAAFFFFFF);
|
||||
|
||||
if (maxInterval > kOneFrameMS) {
|
||||
// Paint the horizontal markers
|
||||
size_t frameMarkerCount = static_cast<size_t>(maxInterval / kOneFrameMS);
|
||||
|
||||
// Limit the number of markers displayed. After a certain point, the graph
|
||||
// becomes crowded
|
||||
if (frameMarkerCount > kMaxFrameMarkers) {
|
||||
frameMarkerCount = 1;
|
||||
}
|
||||
|
||||
for (size_t frameIndex = 0; frameIndex < frameMarkerCount; frameIndex++) {
|
||||
const double frameHeight =
|
||||
height * (1.0 - (UnitFrameInterval((frameIndex + 1) * kOneFrameMS) /
|
||||
maxUnitInterval));
|
||||
canvas.drawLine(0, frameHeight, width, frameHeight, paint);
|
||||
}
|
||||
}
|
||||
|
||||
// Paint the vertical marker
|
||||
if (UnitFrameInterval(lastLap().InMillisecondsF()) > 1.0) {
|
||||
// budget exceeded
|
||||
paint.setColor(SK_ColorRED);
|
||||
} else {
|
||||
// within budget
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
}
|
||||
|
||||
double sampleX = width * (static_cast<double>(_current_sample) / kMaxSamples);
|
||||
paint.setStrokeWidth(3);
|
||||
canvas.drawLine(sampleX, 0, sampleX, height, paint);
|
||||
}
|
||||
|
||||
Stopwatch::~Stopwatch() = default;
|
||||
|
||||
} // namespace instrumentation
|
||||
} // namespace flow
|
||||
76
engine/src/flutter/flow/instrumentation.h
Normal file
76
engine/src/flutter/flow/instrumentation.h
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_INSTRUMENTATION_H_
|
||||
#define FLOW_INSTRUMENTATION_H_
|
||||
|
||||
#include <vector>
|
||||
#include "base/macros.h"
|
||||
#include "base/time/time.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace flow {
|
||||
namespace instrumentation {
|
||||
|
||||
class Stopwatch {
|
||||
public:
|
||||
class ScopedLap {
|
||||
public:
|
||||
explicit ScopedLap(Stopwatch& stopwatch) : _stopwatch(stopwatch) {
|
||||
_stopwatch.start();
|
||||
}
|
||||
|
||||
~ScopedLap() { _stopwatch.stop(); }
|
||||
|
||||
private:
|
||||
Stopwatch& _stopwatch;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedLap);
|
||||
};
|
||||
|
||||
explicit Stopwatch();
|
||||
~Stopwatch();
|
||||
|
||||
const base::TimeDelta& lastLap() const;
|
||||
|
||||
base::TimeDelta currentLap() const { return base::TimeTicks::Now() - _start; }
|
||||
|
||||
void visualize(SkCanvas& canvas, const SkRect& rect) const;
|
||||
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
void setLapTime(const base::TimeDelta& delta);
|
||||
|
||||
private:
|
||||
base::TimeTicks _start;
|
||||
std::vector<base::TimeDelta> _laps;
|
||||
size_t _current_sample;
|
||||
|
||||
base::TimeDelta maxDelta() const;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Stopwatch);
|
||||
};
|
||||
|
||||
class Counter {
|
||||
public:
|
||||
explicit Counter() : _count(0) {}
|
||||
|
||||
size_t count() const { return _count; }
|
||||
|
||||
void reset(size_t count = 0) { _count = count; }
|
||||
|
||||
void increment(size_t count = 1) { _count += count; }
|
||||
|
||||
private:
|
||||
size_t _count;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Counter);
|
||||
};
|
||||
|
||||
} // namespace instrumentation
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_INSTRUMENTATION_H_
|
||||
23
engine/src/flutter/flow/layer.cc
Normal file
23
engine/src/flutter/flow/layer.cc
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/layer.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkColorFilter.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
Layer::Layer()
|
||||
: parent_(nullptr)
|
||||
, has_paint_bounds_(false)
|
||||
, paint_bounds_() {
|
||||
}
|
||||
|
||||
Layer::~Layer() {
|
||||
}
|
||||
|
||||
void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
67
engine/src/flutter/flow/layer.h
Normal file
67
engine/src/flutter/flow/layer.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_LAYER_H_
|
||||
#define FLOW_LAYER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "skia/ext/refptr.h"
|
||||
#include "flow/paint_context.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkColorFilter.h"
|
||||
#include "third_party/skia/include/core/SkMatrix.h"
|
||||
#include "third_party/skia/include/core/SkPath.h"
|
||||
#include "third_party/skia/include/core/SkPicture.h"
|
||||
#include "third_party/skia/include/core/SkRect.h"
|
||||
#include "third_party/skia/include/core/SkRRect.h"
|
||||
#include "third_party/skia/include/core/SkXfermode.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ContainerLayer;
|
||||
class Layer {
|
||||
public:
|
||||
Layer();
|
||||
virtual ~Layer();
|
||||
|
||||
struct PrerollContext {
|
||||
PaintContext::ScopedFrame& frame;
|
||||
SkRect child_paint_bounds;
|
||||
};
|
||||
|
||||
virtual void Preroll(PrerollContext* context, const SkMatrix& matrix);
|
||||
virtual void Paint(PaintContext::ScopedFrame& frame) = 0;
|
||||
|
||||
ContainerLayer* parent() const { return parent_; }
|
||||
|
||||
void set_parent(ContainerLayer* parent) { parent_ = parent; }
|
||||
|
||||
const bool has_paint_bounds() const { return has_paint_bounds_; }
|
||||
|
||||
const SkRect& paint_bounds() const {
|
||||
DCHECK(has_paint_bounds_);
|
||||
return paint_bounds_;
|
||||
}
|
||||
|
||||
void set_paint_bounds(const SkRect& paint_bounds) {
|
||||
has_paint_bounds_ = true;
|
||||
paint_bounds_ = paint_bounds;
|
||||
}
|
||||
|
||||
private:
|
||||
ContainerLayer* parent_;
|
||||
bool has_paint_bounds_; // if false, paint_bounds_ is not valid
|
||||
SkRect paint_bounds_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Layer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_LAYER_H_
|
||||
31
engine/src/flutter/flow/layer_tree.cc
Normal file
31
engine/src/flutter/flow/layer_tree.cc
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/layer_tree.h"
|
||||
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "flow/layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
LayerTree::LayerTree() : rasterizer_tracing_threashold_(0) {
|
||||
}
|
||||
|
||||
LayerTree::~LayerTree() {
|
||||
}
|
||||
|
||||
void LayerTree::Raster(PaintContext::ScopedFrame& frame) {
|
||||
{
|
||||
TRACE_EVENT0("flutter", "LayerTree::Preroll")
|
||||
Layer::PrerollContext context = { frame, SkRect::MakeEmpty() };
|
||||
root_layer_->Preroll(&context, SkMatrix());
|
||||
}
|
||||
|
||||
{
|
||||
TRACE_EVENT0("flutter", "LayerTree::Paint")
|
||||
root_layer_->Paint(frame);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
66
engine/src/flutter/flow/layer_tree.h
Normal file
66
engine/src/flutter/flow/layer_tree.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_LAYER_TREE_H_
|
||||
#define FLOW_LAYER_TREE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/time/time.h"
|
||||
#include "flow/layer.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class LayerTree {
|
||||
public:
|
||||
LayerTree();
|
||||
~LayerTree();
|
||||
|
||||
void Raster(PaintContext::ScopedFrame& frame);
|
||||
|
||||
Layer* root_layer() const { return root_layer_.get(); }
|
||||
|
||||
void set_root_layer(std::unique_ptr<Layer> root_layer) {
|
||||
root_layer_ = std::move(root_layer);
|
||||
}
|
||||
|
||||
const SkISize& frame_size() const { return frame_size_; }
|
||||
|
||||
void set_frame_size(const SkISize& frame_size) { frame_size_ = frame_size; }
|
||||
|
||||
void set_construction_time(const base::TimeDelta& delta) {
|
||||
construction_time_ = delta;
|
||||
}
|
||||
|
||||
const base::TimeDelta& construction_time() const {
|
||||
return construction_time_;
|
||||
}
|
||||
|
||||
// The number of frame intervals missed after which the compositor must
|
||||
// trace the rasterized picture to a trace file. Specify 0 to disable all
|
||||
// tracing
|
||||
void set_rasterizer_tracing_threshold(uint32_t interval) {
|
||||
rasterizer_tracing_threashold_ = interval;
|
||||
}
|
||||
|
||||
uint32_t rasterizer_tracing_threshold() const {
|
||||
return rasterizer_tracing_threashold_;
|
||||
}
|
||||
|
||||
private:
|
||||
SkISize frame_size_; // Physical pixels.
|
||||
std::unique_ptr<Layer> root_layer_;
|
||||
|
||||
base::TimeDelta construction_time_;
|
||||
uint32_t rasterizer_tracing_threashold_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LayerTree);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_LAYER_TREE_H_
|
||||
31
engine/src/flutter/flow/opacity_layer.cc
Normal file
31
engine/src/flutter/flow/opacity_layer.cc
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/opacity_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
OpacityLayer::OpacityLayer() {
|
||||
}
|
||||
|
||||
OpacityLayer::~OpacityLayer() {
|
||||
}
|
||||
|
||||
void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
set_paint_bounds(context->child_paint_bounds);
|
||||
}
|
||||
|
||||
void OpacityLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
SkPaint paint;
|
||||
paint.setColor(SkColorSetARGB(alpha_, 0, 0, 0));
|
||||
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
||||
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, false);
|
||||
canvas.saveLayer(&paint_bounds(), &paint);
|
||||
PaintChildren(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
31
engine/src/flutter/flow/opacity_layer.h
Normal file
31
engine/src/flutter/flow/opacity_layer.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_OPACITY_LAYER_H_
|
||||
#define FLOW_OPACITY_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class OpacityLayer : public ContainerLayer {
|
||||
public:
|
||||
OpacityLayer();
|
||||
~OpacityLayer() override;
|
||||
|
||||
void set_alpha(int alpha) { alpha_ = alpha; }
|
||||
|
||||
protected:
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
int alpha_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_OPACITY_LAYER_H_
|
||||
52
engine/src/flutter/flow/paint_context.cc
Normal file
52
engine/src/flutter/flow/paint_context.cc
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/paint_context.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
PaintContext::PaintContext() {
|
||||
}
|
||||
|
||||
void PaintContext::beginFrame(ScopedFrame& frame, bool enableInstrumentation) {
|
||||
if (enableInstrumentation) {
|
||||
frame_count_.increment();
|
||||
frame_time_.start();
|
||||
}
|
||||
}
|
||||
|
||||
void PaintContext::endFrame(ScopedFrame& frame, bool enableInstrumentation) {
|
||||
raster_cache_.SweepAfterFrame();
|
||||
if (enableInstrumentation) {
|
||||
frame_time_.stop();
|
||||
}
|
||||
}
|
||||
|
||||
PaintContext::ScopedFrame PaintContext::AcquireFrame(
|
||||
GrContext* gr_context, SkCanvas& canvas, bool instrumentation_enabled) {
|
||||
return ScopedFrame(*this, gr_context, canvas, instrumentation_enabled);
|
||||
}
|
||||
|
||||
PaintContext::ScopedFrame::ScopedFrame(PaintContext& 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_);
|
||||
}
|
||||
|
||||
PaintContext::ScopedFrame::ScopedFrame(ScopedFrame&& frame) = default;
|
||||
|
||||
PaintContext::ScopedFrame::~ScopedFrame() {
|
||||
context_.endFrame(*this, instrumentation_enabled_);
|
||||
}
|
||||
|
||||
PaintContext::~PaintContext() {
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
74
engine/src/flutter/flow/paint_context.h
Normal file
74
engine/src/flutter/flow/paint_context.h
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_PAINT_CONTEXT_H_
|
||||
#define FLOW_PAINT_CONTEXT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/logging.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"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class PaintContext {
|
||||
public:
|
||||
class ScopedFrame {
|
||||
public:
|
||||
SkCanvas& canvas() { return *canvas_; }
|
||||
PaintContext& context() const { return context_; }
|
||||
GrContext* gr_context() const { return gr_context_; }
|
||||
|
||||
ScopedFrame(ScopedFrame&& frame);
|
||||
~ScopedFrame();
|
||||
|
||||
private:
|
||||
PaintContext& context_;
|
||||
GrContext* gr_context_;
|
||||
SkCanvas* canvas_;
|
||||
const bool instrumentation_enabled_;
|
||||
|
||||
ScopedFrame(PaintContext& context,
|
||||
GrContext* gr_context,
|
||||
SkCanvas& canvas,
|
||||
bool instrumentation_enabled);
|
||||
|
||||
friend class PaintContext;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedFrame);
|
||||
};
|
||||
|
||||
PaintContext();
|
||||
~PaintContext();
|
||||
|
||||
ScopedFrame AcquireFrame(GrContext* gr_context,
|
||||
SkCanvas& canvas,
|
||||
bool instrumentation_enabled = true);
|
||||
|
||||
RasterCache& raster_cache() { return raster_cache_; }
|
||||
const instrumentation::Counter& frame_count() const { return frame_count_; }
|
||||
const instrumentation::Stopwatch& frame_time() const { return frame_time_; }
|
||||
instrumentation::Stopwatch& engine_time() { return engine_time_; };
|
||||
|
||||
private:
|
||||
RasterCache raster_cache_;
|
||||
|
||||
instrumentation::Counter frame_count_;
|
||||
instrumentation::Stopwatch frame_time_;
|
||||
instrumentation::Stopwatch engine_time_;
|
||||
|
||||
void beginFrame(ScopedFrame& frame, bool enableInstrumentation);
|
||||
void endFrame(ScopedFrame& frame, bool enableInstrumentation);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PaintContext);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_PAINT_CONTEXT_H_
|
||||
79
engine/src/flutter/flow/performance_overlay_layer.cc
Normal file
79
engine/src/flutter/flow/performance_overlay_layer.cc
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "flow/performance_overlay_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
PerformanceOverlayLayer::PerformanceOverlayLayer(uint64_t enabledOptions)
|
||||
: options_(enabledOptions) {
|
||||
}
|
||||
|
||||
static void DrawStatisticsText(SkCanvas& canvas,
|
||||
const std::string& string,
|
||||
int x,
|
||||
int y) {
|
||||
SkPaint paint;
|
||||
paint.setTextSize(14);
|
||||
paint.setLinearText(false);
|
||||
paint.setColor(SK_ColorRED);
|
||||
canvas.drawText(string.c_str(), string.size(), x, y, paint);
|
||||
}
|
||||
|
||||
static void VisualizeStopWatch(SkCanvas& canvas,
|
||||
const instrumentation::Stopwatch& stopwatch,
|
||||
SkScalar width,
|
||||
bool show_graph,
|
||||
bool show_labels,
|
||||
std::string label_prefix) {
|
||||
const int x = 8;
|
||||
const int y = 70;
|
||||
const int height = 80;
|
||||
|
||||
if (show_graph) {
|
||||
SkRect visualizationRect = SkRect::MakeWH(width, height);
|
||||
stopwatch.visualize(canvas, visualizationRect);
|
||||
}
|
||||
|
||||
if (show_labels) {
|
||||
double msPerFrame = stopwatch.lastLap().InMillisecondsF();
|
||||
double fps = 1e3 / msPerFrame;
|
||||
|
||||
std::stringstream stream;
|
||||
stream.setf(std::ios::fixed | std::ios::showpoint);
|
||||
stream << std::setprecision(2);
|
||||
stream << label_prefix << " " << fps << " FPS | " << msPerFrame
|
||||
<< "ms/frame";
|
||||
DrawStatisticsText(canvas, stream.str(), x, y);
|
||||
}
|
||||
|
||||
if (show_labels || show_graph) {
|
||||
canvas.translate(0, height);
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceOverlayLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
if (!options_) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkScalar width = has_paint_bounds() ? paint_bounds().width() : 0;
|
||||
SkAutoCanvasRestore save(&frame.canvas(), true);
|
||||
|
||||
VisualizeStopWatch(frame.canvas(), frame.context().frame_time(), width,
|
||||
options_ & kVisualizeRasterizerStatistics,
|
||||
options_ & kDisplayRasterizerStatistics,
|
||||
"Rasterizer");
|
||||
|
||||
VisualizeStopWatch(frame.canvas(), frame.context().engine_time(), width,
|
||||
options_ & kVisualizeEngineStatistics,
|
||||
options_ & kDisplayEngineStatistics,
|
||||
"Engine");
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
32
engine/src/flutter/flow/performance_overlay_layer.h
Normal file
32
engine/src/flutter/flow/performance_overlay_layer.h
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_PERFORMANCE_OVERLAY_LAYER_H_
|
||||
#define FLOW_PERFORMANCE_OVERLAY_LAYER_H_
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "flow/layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
const int kDisplayRasterizerStatistics = 0x01;
|
||||
const int kVisualizeRasterizerStatistics = 0x02;
|
||||
const int kDisplayEngineStatistics = 0x04;
|
||||
const int kVisualizeEngineStatistics = 0x08;
|
||||
|
||||
class PerformanceOverlayLayer : public Layer {
|
||||
public:
|
||||
explicit PerformanceOverlayLayer(uint64_t enabledOptions);
|
||||
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
int options_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PerformanceOverlayLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_PERFORMANCE_OVERLAY_LAYER_H_
|
||||
45
engine/src/flutter/flow/picture_layer.cc
Normal file
45
engine/src/flutter/flow/picture_layer.cc
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/picture_layer.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "flow/checkerboard.h"
|
||||
#include "flow/raster_cache.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
// TODO(abarth): Make this configurable by developers.
|
||||
const bool kDebugCheckerboardRasterizedLayers = false;
|
||||
|
||||
PictureLayer::PictureLayer() {
|
||||
}
|
||||
|
||||
PictureLayer::~PictureLayer() {
|
||||
}
|
||||
|
||||
void PictureLayer::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
image_ = context->frame.context().raster_cache().GetPrerolledImage(
|
||||
context->frame.gr_context(), picture_.get(), matrix);
|
||||
context->child_paint_bounds = picture_->cullRect().makeOffset(offset_.x(), offset_.y());
|
||||
}
|
||||
|
||||
void PictureLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
DCHECK(picture_);
|
||||
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
if (image_) {
|
||||
SkRect rect = picture_->cullRect().makeOffset(offset_.x(), offset_.y());
|
||||
canvas.drawImageRect(image_.get(), rect, nullptr, SkCanvas::kFast_SrcRectConstraint);
|
||||
if (kDebugCheckerboardRasterizedLayers)
|
||||
DrawCheckerboard(&canvas, rect);
|
||||
} else {
|
||||
SkAutoCanvasRestore save(&canvas, true);
|
||||
canvas.translate(offset_.x(), offset_.y());
|
||||
canvas.drawPicture(picture_.get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
38
engine/src/flutter/flow/picture_layer.h
Normal file
38
engine/src/flutter/flow/picture_layer.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_PICTURE_LAYER_H_
|
||||
#define FLOW_PICTURE_LAYER_H_
|
||||
|
||||
#include "flow/layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class PictureLayer : public Layer {
|
||||
public:
|
||||
PictureLayer();
|
||||
~PictureLayer() override;
|
||||
|
||||
void set_offset(const SkPoint& offset) { offset_ = offset; }
|
||||
|
||||
void set_picture(SkPicture* picture) { picture_ = skia::SharePtr(picture); }
|
||||
|
||||
SkPicture* picture() const { return picture_.get(); }
|
||||
|
||||
void Preroll(PrerollContext* frame, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
SkPoint offset_;
|
||||
skia::RefPtr<SkPicture> picture_;
|
||||
|
||||
// If we rasterized the picture separately, image_ holds the pixels.
|
||||
skia::RefPtr<SkImage> image_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PictureLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_PICTURE_LAYER_H_
|
||||
114
engine/src/flutter/flow/raster_cache.cc
Normal file
114
engine/src/flutter/flow/raster_cache.cc
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/raster_cache.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "flow/paint_context.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkImage.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
|
||||
#define ENABLE_RASTER_CACHE 1
|
||||
|
||||
namespace flow {
|
||||
|
||||
#if ENABLE_RASTER_CACHE
|
||||
|
||||
static const int kRasterThreshold = 3;
|
||||
|
||||
static bool isWorthRasterizing(SkPicture* picture) {
|
||||
// TODO(abarth): We should find a better heuristic here that lets us avoid
|
||||
// wasting memory on trivial layers that are easy to re-rasterize every frame.
|
||||
return picture->approximateOpCount() > 10 || picture->hasText();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
RasterCache::RasterCache() {
|
||||
}
|
||||
|
||||
RasterCache::~RasterCache() {
|
||||
}
|
||||
|
||||
RasterCache::Entry::Entry() {
|
||||
physical_size.setEmpty();
|
||||
}
|
||||
|
||||
RasterCache::Entry::~Entry() {
|
||||
}
|
||||
|
||||
skia::RefPtr<SkImage> RasterCache::GetPrerolledImage(GrContext* context,
|
||||
SkPicture* picture,
|
||||
const SkMatrix& ctm) {
|
||||
#if ENABLE_RASTER_CACHE
|
||||
SkScalar scaleX = ctm.getScaleX();
|
||||
SkScalar scaleY = ctm.getScaleY();
|
||||
|
||||
SkRect rect = picture->cullRect();
|
||||
|
||||
SkISize physical_size = SkISize::Make(rect.width() * scaleX,
|
||||
rect.height() * scaleY);
|
||||
|
||||
if (physical_size.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
Entry& entry = cache_[picture->uniqueID()];
|
||||
|
||||
const bool size_matched = entry.physical_size == physical_size;
|
||||
|
||||
entry.used_this_frame = true;
|
||||
entry.physical_size = physical_size;
|
||||
|
||||
if (!size_matched) {
|
||||
entry.access_count = 1;
|
||||
entry.image = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
entry.access_count++;
|
||||
|
||||
if (entry.access_count >= kRasterThreshold) {
|
||||
// Saturate at the threshhold.
|
||||
entry.access_count = kRasterThreshold;
|
||||
|
||||
if (!entry.image && isWorthRasterizing(picture)) {
|
||||
TRACE_EVENT2("flutter", "Rasterize picture layer",
|
||||
"width", physical_size.width(),
|
||||
"height", physical_size.height());
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(physical_size);
|
||||
skia::RefPtr<SkSurface> surface = skia::AdoptRef(
|
||||
SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted, info));
|
||||
if (surface) {
|
||||
SkCanvas* canvas = surface->getCanvas();
|
||||
canvas->clear(SK_ColorTRANSPARENT);
|
||||
SkMatrix matrix = SkMatrix::MakeScale(scaleX, scaleY);
|
||||
canvas->drawPicture(picture, &matrix, nullptr);
|
||||
entry.image = skia::AdoptRef(surface->newImageSnapshot());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entry.image;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RasterCache::SweepAfterFrame() {
|
||||
std::vector<Cache::iterator> dead;
|
||||
|
||||
for (auto it = cache_.begin(); it != cache_.end(); ++it) {
|
||||
Entry& entry = it->second;
|
||||
if (!entry.used_this_frame)
|
||||
dead.push_back(it);
|
||||
entry.used_this_frame = false;
|
||||
}
|
||||
|
||||
for (auto it : dead)
|
||||
cache_.erase(it);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
47
engine/src/flutter/flow/raster_cache.h
Normal file
47
engine/src/flutter/flow/raster_cache.h
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_RASTER_CACHE_H_
|
||||
#define FLOW_RASTER_CACHE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "skia/ext/refptr.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
#include "third_party/skia/include/core/SkImage.h"
|
||||
#include "flow/instrumentation.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class RasterCache {
|
||||
public:
|
||||
RasterCache();
|
||||
~RasterCache();
|
||||
|
||||
skia::RefPtr<SkImage> GetPrerolledImage(
|
||||
GrContext* context, SkPicture* picture, const SkMatrix& ctm);
|
||||
void SweepAfterFrame();
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
Entry();
|
||||
~Entry();
|
||||
|
||||
bool used_this_frame = false;
|
||||
int access_count = 0;
|
||||
SkISize physical_size;
|
||||
skia::RefPtr<SkImage> image;
|
||||
};
|
||||
|
||||
using Cache = std::unordered_map<uint32_t, Entry>;
|
||||
Cache cache_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RasterCache);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_RASTER_CACHE_H_
|
||||
33
engine/src/flutter/flow/shader_mask_layer.cc
Normal file
33
engine/src/flutter/flow/shader_mask_layer.cc
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/shader_mask_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
ShaderMaskLayer::ShaderMaskLayer() {
|
||||
}
|
||||
|
||||
ShaderMaskLayer::~ShaderMaskLayer() {
|
||||
}
|
||||
|
||||
void ShaderMaskLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
set_paint_bounds(context->child_paint_bounds);
|
||||
}
|
||||
|
||||
void ShaderMaskLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, false);
|
||||
canvas.saveLayer(&paint_bounds(), nullptr);
|
||||
PaintChildren(frame);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(transfer_mode_);
|
||||
paint.setShader(shader_.get());
|
||||
canvas.translate(mask_rect_.left(), mask_rect_.top());
|
||||
canvas.drawRect(SkRect::MakeWH(mask_rect_.width(), mask_rect_.height()), paint);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
43
engine/src/flutter/flow/shader_mask_layer.h
Normal file
43
engine/src/flutter/flow/shader_mask_layer.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_SHADER_MASK_LAYER_H_
|
||||
#define FLOW_SHADER_MASK_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkShader.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class ShaderMaskLayer : public ContainerLayer {
|
||||
public:
|
||||
ShaderMaskLayer();
|
||||
~ShaderMaskLayer() override;
|
||||
|
||||
void set_shader(SkShader* shader) { shader_ = skia::SharePtr(shader); }
|
||||
|
||||
void set_mask_rect(const SkRect& mask_rect) {
|
||||
mask_rect_ = mask_rect;
|
||||
}
|
||||
|
||||
void set_transfer_mode(SkXfermode::Mode transfer_mode) {
|
||||
transfer_mode_ = transfer_mode;
|
||||
}
|
||||
|
||||
protected:
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
skia::RefPtr<SkShader> shader_;
|
||||
SkRect mask_rect_;
|
||||
SkXfermode::Mode transfer_mode_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ShaderMaskLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_SHADER_MASK_LAYER_H_
|
||||
29
engine/src/flutter/flow/transform_layer.cc
Normal file
29
engine/src/flutter/flow/transform_layer.cc
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flow/transform_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
TransformLayer::TransformLayer() {
|
||||
}
|
||||
|
||||
TransformLayer::~TransformLayer() {
|
||||
}
|
||||
|
||||
void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
SkMatrix childMatrix;
|
||||
childMatrix.setConcat(matrix, transform_);
|
||||
PrerollChildren(context, childMatrix);
|
||||
transform_.mapRect(&context->child_paint_bounds);
|
||||
}
|
||||
|
||||
void TransformLayer::Paint(PaintContext::ScopedFrame& frame) {
|
||||
SkCanvas& canvas = frame.canvas();
|
||||
SkAutoCanvasRestore save(&canvas, true);
|
||||
canvas.concat(transform_);
|
||||
PaintChildren(frame);
|
||||
}
|
||||
|
||||
} // namespace flow
|
||||
30
engine/src/flutter/flow/transform_layer.h
Normal file
30
engine/src/flutter/flow/transform_layer.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLOW_TRANSFORM_LAYER_H_
|
||||
#define FLOW_TRANSFORM_LAYER_H_
|
||||
|
||||
#include "flow/container_layer.h"
|
||||
|
||||
namespace flow {
|
||||
|
||||
class TransformLayer : public ContainerLayer {
|
||||
public:
|
||||
TransformLayer();
|
||||
~TransformLayer() override;
|
||||
|
||||
void set_transform(const SkMatrix& transform) { transform_ = transform; }
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext::ScopedFrame& frame) override;
|
||||
|
||||
private:
|
||||
SkMatrix transform_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TransformLayer);
|
||||
};
|
||||
|
||||
} // namespace flow
|
||||
|
||||
#endif // FLOW_TRANSFORM_LAYER_H_
|
||||
Loading…
x
Reference in New Issue
Block a user