提交 df5f62f2 编写于 作者: J Jason Simmons 提交者: GitHub

Add a flag that checkerboards offscreen render targets created by SkCanvas.saveLayer (#3685)

Fixes https://github.com/flutter/flutter/issues/9473
上级 f99d3ef1
......@@ -36,6 +36,8 @@ source_set("flow") {
"layers/shader_mask_layer.h",
"layers/transform_layer.cc",
"layers/transform_layer.h",
"paint_utils.cc",
"paint_utils.h",
"process_info.h",
"raster_cache.cc",
"raster_cache.h",
......
......@@ -14,8 +14,8 @@ BackdropFilterLayer::~BackdropFilterLayer() {}
void BackdropFilterLayer::Paint(PaintContext& context) {
TRACE_EVENT0("flutter", "BackdropFilterLayer::Paint");
SkAutoCanvasRestore save(&context.canvas, false);
context.canvas.saveLayer(
Layer::AutoSaveLayer(
context,
SkCanvas::SaveLayerRec{&paint_bounds(), nullptr, filter_.get(), 0});
PaintChildren(context);
}
......
......@@ -37,8 +37,7 @@ void ClipPathLayer::Paint(PaintContext& context) {
TRACE_EVENT0("flutter", "ClipPathLayer::Paint");
FTL_DCHECK(!needs_system_composite());
SkAutoCanvasRestore save(&context.canvas, false);
context.canvas.saveLayer(&paint_bounds(), nullptr);
Layer::AutoSaveLayer save(context, paint_bounds(), nullptr);
context.canvas.clipPath(clip_path_, true);
PaintChildren(context);
}
......
......@@ -37,8 +37,7 @@ void ClipRRectLayer::Paint(PaintContext& context) {
TRACE_EVENT0("flutter", "ClipRRectLayer::Paint");
FTL_DCHECK(!needs_system_composite());
SkAutoCanvasRestore save(&context.canvas, false);
context.canvas.saveLayer(&paint_bounds(), nullptr);
Layer::AutoSaveLayer save(context, paint_bounds(), nullptr);
context.canvas.clipRRect(clip_rrect_, true);
PaintChildren(context);
}
......
......@@ -17,8 +17,7 @@ void ColorFilterLayer::Paint(PaintContext& context) {
SkPaint paint;
paint.setColorFilter(std::move(color_filter));
SkAutoCanvasRestore save(&context.canvas, false);
context.canvas.saveLayer(&paint_bounds(), &paint);
Layer::AutoSaveLayer(context, paint_bounds(), nullptr);
PaintChildren(context);
}
......
......@@ -4,6 +4,7 @@
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/paint_utils.h"
#include "third_party/skia/include/core/SkColorFilter.h"
namespace flow {
......@@ -26,4 +27,26 @@ void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
void Layer::UpdateScene(SceneUpdateContext& context, mozart::Node* container) {}
#endif
Layer::AutoSaveLayer::AutoSaveLayer(const PaintContext& paint_context,
const SkRect& bounds,
const SkPaint* paint)
: paint_context_(paint_context),
bounds_(bounds) {
paint_context_.canvas.saveLayer(bounds_, paint);
}
Layer::AutoSaveLayer::AutoSaveLayer(const PaintContext& paint_context,
const SkCanvas::SaveLayerRec& layer_rec)
: paint_context_(paint_context),
bounds_(*layer_rec.fBounds) {
paint_context_.canvas.saveLayer(layer_rec);
}
Layer::AutoSaveLayer::~AutoSaveLayer() {
if (paint_context_.checkerboard_offscreen_layers) {
DrawCheckerboard(&paint_context_.canvas, bounds_);
}
paint_context_.canvas.restore();
}
} // namespace flow
......@@ -45,6 +45,25 @@ class Layer {
const Stopwatch& frame_time;
const Stopwatch& engine_time;
const CounterValues& memory_usage;
const bool checkerboard_offscreen_layers;
};
// Calls SkCanvas::saveLayer and restores the layer upon destruction. Also
// draws a checkerboard over the layer if that is enabled in the PaintContext.
class AutoSaveLayer {
public:
AutoSaveLayer(const PaintContext& paint_context,
const SkRect& bounds,
const SkPaint* paint);
AutoSaveLayer(const PaintContext& paint_context,
const SkCanvas::SaveLayerRec& layer_rec);
~AutoSaveLayer();
private:
const PaintContext& paint_context_;
const SkRect bounds_;
};
virtual void Paint(PaintContext& context) = 0;
......
......@@ -13,7 +13,8 @@ LayerTree::LayerTree()
: frame_size_{},
scene_version_(0),
rasterizer_tracing_threshold_(0),
checkerboard_raster_cache_images_(false) {}
checkerboard_raster_cache_images_(false),
checkerboard_offscreen_layers_(false) {}
LayerTree::~LayerTree() {}
......@@ -52,7 +53,8 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
void LayerTree::Paint(CompositorContext::ScopedFrame& frame) {
Layer::PaintContext context = {frame.canvas(), frame.context().frame_time(),
frame.context().engine_time(),
frame.context().memory_usage()};
frame.context().memory_usage(),
checkerboard_offscreen_layers_};
TRACE_EVENT0("flutter", "LayerTree::Paint");
root_layer_->Paint(context);
}
......
......@@ -76,6 +76,10 @@ class LayerTree {
checkerboard_raster_cache_images_ = checkerboard;
}
void set_checkerboard_offscreen_layers(bool checkerboard) {
checkerboard_offscreen_layers_ = checkerboard;
}
private:
SkISize frame_size_; // Physical pixels.
uint32_t scene_version_;
......@@ -83,6 +87,7 @@ class LayerTree {
ftl::TimeDelta construction_time_;
uint32_t rasterizer_tracing_threshold_;
bool checkerboard_raster_cache_images_;
bool checkerboard_offscreen_layers_;
FTL_DISALLOW_COPY_AND_ASSIGN(LayerTree);
};
......
......@@ -37,8 +37,7 @@ void OpacityLayer::Paint(PaintContext& context) {
SkPaint paint;
paint.setAlpha(alpha_);
SkAutoCanvasRestore save(&context.canvas, false);
context.canvas.saveLayer(&paint_bounds(), &paint);
Layer::AutoSaveLayer save(context, paint_bounds(), &paint);
PaintChildren(context);
}
......
......@@ -4,6 +4,7 @@
#include "flutter/flow/layers/physical_model_layer.h"
#include "flutter/flow/paint_utils.h"
#include "third_party/skia/include/utils/SkShadowUtils.h"
#if defined(OS_FUCHSIA)
......@@ -69,6 +70,8 @@ void PhysicalModelLayer::Paint(PaintContext& context) {
}
context.canvas.clipRRect(rrect_, true);
PaintChildren(context);
if (context.checkerboard_offscreen_layers && !rrect_.isRect())
DrawCheckerboard(&context.canvas, rrect_.getBounds());
}
void PhysicalModelLayer::DrawShadow(SkCanvas* canvas, const SkPath& path,
......
......@@ -12,8 +12,7 @@ ShaderMaskLayer::~ShaderMaskLayer() {}
void ShaderMaskLayer::Paint(PaintContext& context) {
TRACE_EVENT0("flutter", "ShaderMaskLayer::Paint");
SkAutoCanvasRestore save(&context.canvas, false);
context.canvas.saveLayer(&paint_bounds(), nullptr);
Layer::AutoSaveLayer(context, paint_bounds(), nullptr);
PaintChildren(context);
SkPaint paint;
......
// Copyright 2017 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 "flutter/flow/paint_utils.h"
#include <stdlib.h>
#include "third_party/skia/include/core/SkShader.h"
namespace flow {
namespace {
sk_sp<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::MakeBitmapShader(bm, SkShader::kRepeat_TileMode,
SkShader::kRepeat_TileMode);
}
} // anonymous namespace
void DrawCheckerboard(SkCanvas* canvas,
SkColor c1,
SkColor c2,
int size) {
SkPaint paint;
paint.setShader(CreateCheckerboardShader(c1, c2, size));
canvas->drawPaint(paint);
}
void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect) {
// Draw a checkerboard
canvas->save();
canvas->clipRect(rect);
auto checkerboard_color =
SkColorSetARGBInline(64, rand() % 256, rand() % 256, rand() % 256);
DrawCheckerboard(canvas, checkerboard_color, 0x00000000, 12);
canvas->restore();
// Stroke the drawn area
SkPaint debugPaint;
debugPaint.setStrokeWidth(8);
debugPaint.setColor(SkColorSetA(checkerboard_color, 255));
debugPaint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(rect, debugPaint);
}
} // namespace flow
// Copyright 2017 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 FLUTTER_FLOW_PAINT_UTILS_H_
#define FLUTTER_FLOW_PAINT_UTILS_H_
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRect.h"
namespace flow {
void DrawCheckerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size);
void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect);
} // namespace flow
#endif // FLUTTER_FLOW_PAINT_UTILS_H_
......@@ -4,11 +4,10 @@
#include "flutter/flow/raster_cache.h"
#include <stdlib.h>
#include <vector>
#include "flutter/common/threads.h"
#include "flutter/flow/paint_utils.h"
#include "flutter/glue/trace_event.h"
#include "lib/ftl/logging.h"
#include "third_party/skia/include/core/SkCanvas.h"
......@@ -26,46 +25,6 @@ static bool isWorthRasterizing(SkPicture* picture) {
return picture->approximateOpCount() > 10;
}
static sk_sp<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::MakeBitmapShader(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));
canvas->drawPaint(paint);
}
static void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect) {
// Draw a checkerboard
canvas->save();
canvas->clipRect(rect);
auto checkerboard_color =
SkColorSetARGBInline(64, rand() % 256, rand() % 256, rand() % 256);
DrawCheckerboard(canvas, checkerboard_color, 0x00000000, 12);
canvas->restore();
// Stroke the drawn area
SkPaint debugPaint;
debugPaint.setStrokeWidth(8);
debugPaint.setColor(SkColorSetA(checkerboard_color, 255));
debugPaint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(rect, debugPaint);
}
RasterCache::RasterCache() : checkerboard_images_(false), weak_factory_(this) {}
RasterCache::~RasterCache() {}
......
......@@ -109,7 +109,8 @@ void SceneUpdateContext::ExecutePaintTasks(
SkCanvas* canvas = task.surface->getCanvas();
Layer::PaintContext context = {*canvas, frame.context().frame_time(),
frame.context().engine_time(),
frame.context().memory_usage()};
frame.context().memory_usage(),
false};
canvas->clear(SK_ColorTRANSPARENT);
canvas->scale(task.scaleX, task.scaleY);
......
......@@ -252,6 +252,12 @@ class SceneBuilder extends NativeFieldWrapperClass2 {
/// interested in using this feature, please contact [flutter-dev](https://groups.google.com/forum/#!forum/flutter-dev).
void setCheckerboardRasterCacheImages(bool checkerboard) native "SceneBuilder_setCheckerboardRasterCacheImages";
/// Sets whether the compositor should checkerboard layers that are rendered
/// to offscreen bitmaps.
///
/// This is only useful for debugging purposes.
void setCheckerboardOffscreenLayers(bool checkerboard) native "SceneBuilder_setCheckerboardOffscreenLayers";
/// Finishes building the scene.
///
/// Returns a [Scene] containing the objects that have been added to
......
......@@ -21,20 +21,25 @@ DART_BIND_ALL(Scene, FOR_EACH_BINDING)
ftl::RefPtr<Scene> Scene::create(std::unique_ptr<flow::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages) {
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers) {
return ftl::MakeRefCounted<Scene>(std::move(rootLayer),
rasterizerTracingThreshold,
checkerboardRasterCacheImages);
checkerboardRasterCacheImages,
checkerboardOffscreenLayers);
}
Scene::Scene(std::unique_ptr<flow::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages)
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers)
: m_layerTree(new flow::LayerTree()) {
m_layerTree->set_root_layer(std::move(rootLayer));
m_layerTree->set_rasterizer_tracing_threshold(rasterizerTracingThreshold);
m_layerTree->set_checkerboard_raster_cache_images(
checkerboardRasterCacheImages);
m_layerTree->set_checkerboard_offscreen_layers(
checkerboardOffscreenLayers);
}
Scene::~Scene() {}
......
......@@ -27,7 +27,8 @@ class Scene : public ftl::RefCountedThreadSafe<Scene>,
~Scene() override;
static ftl::RefPtr<Scene> create(std::unique_ptr<flow::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages);
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers);
std::unique_ptr<flow::LayerTree> takeLayerTree();
......@@ -38,7 +39,8 @@ class Scene : public ftl::RefCountedThreadSafe<Scene>,
private:
explicit Scene(std::unique_ptr<flow::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages);
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers);
std::unique_ptr<flow::LayerTree> m_layerTree;
};
......
......@@ -52,6 +52,7 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder);
V(SceneBuilder, addChildScene) \
V(SceneBuilder, addPerformanceOverlay) \
V(SceneBuilder, setRasterizerTracingThreshold) \
V(SceneBuilder, setCheckerboardOffscreenLayers) \
V(SceneBuilder, setCheckerboardRasterCacheImages) \
V(SceneBuilder, build)
......@@ -66,7 +67,8 @@ void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) {
SceneBuilder::SceneBuilder()
: m_currentLayer(nullptr),
m_currentRasterizerTracingThreshold(0),
m_checkerboardRasterCacheImages(false) {
m_checkerboardRasterCacheImages(false),
m_checkerboardOffscreenLayers(false) {
m_cullRects.push(SkRect::MakeLargest());
}
......@@ -261,12 +263,17 @@ void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) {
m_checkerboardRasterCacheImages = checkerboard;
}
void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
m_checkerboardOffscreenLayers = checkerboard;
}
ftl::RefPtr<Scene> SceneBuilder::build() {
m_currentLayer = nullptr;
int32_t threshold = m_currentRasterizerTracingThreshold;
m_currentRasterizerTracingThreshold = 0;
ftl::RefPtr<Scene> scene = Scene::create(std::move(m_rootLayer), threshold,
m_checkerboardRasterCacheImages);
m_checkerboardRasterCacheImages,
m_checkerboardOffscreenLayers);
ClearDartWrapper();
return scene;
}
......
......@@ -67,6 +67,7 @@ class SceneBuilder : public ftl::RefCountedThreadSafe<SceneBuilder>,
void setRasterizerTracingThreshold(uint32_t frameInterval);
void setCheckerboardRasterCacheImages(bool checkerboard);
void setCheckerboardOffscreenLayers(bool checkerboard);
ftl::RefPtr<Scene> build();
......@@ -82,6 +83,7 @@ class SceneBuilder : public ftl::RefCountedThreadSafe<SceneBuilder>,
flow::ContainerLayer* m_currentLayer;
int32_t m_currentRasterizerTracingThreshold;
bool m_checkerboardRasterCacheImages;
bool m_checkerboardOffscreenLayers;
std::stack<SkRect> m_cullRects;
};
......
......@@ -1367,6 +1367,8 @@ FILE: ../../../flutter/content_handler/vulkan_rasterizer.cc
FILE: ../../../flutter/content_handler/vulkan_rasterizer.h
FILE: ../../../flutter/flow/layers/physical_model_layer.cc
FILE: ../../../flutter/flow/layers/physical_model_layer.h
FILE: ../../../flutter/flow/paint_utils.cc
FILE: ../../../flutter/flow/paint_utils.h
FILE: ../../../flutter/fml/icu_util.cc
FILE: ../../../flutter/fml/icu_util.h
FILE: ../../../flutter/fml/mapping.cc
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册