Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@

namespace flutter {

LayerTree::LayerTree(const SkISize& frame_size, float device_pixel_ratio)
: frame_size_(frame_size),
device_pixel_ratio_(device_pixel_ratio),
rasterizer_tracing_threshold_(0),
checkerboard_raster_cache_images_(false),
checkerboard_offscreen_layers_(false) {
FML_CHECK(device_pixel_ratio_ != 0.0f);
}
LayerTree::LayerTree(const Config& config, const SkISize& frame_size)
: root_layer_(config.root_layer),
frame_size_(frame_size),
rasterizer_tracing_threshold_(config.rasterizer_tracing_threshold),
checkerboard_raster_cache_images_(
config.checkerboard_raster_cache_images),
checkerboard_offscreen_layers_(config.checkerboard_offscreen_layers) {}

inline SkColorSpace* GetColorSpace(DlCanvas* canvas) {
return canvas ? canvas->GetImageInfo().colorSpace() : nullptr;
Expand Down
32 changes: 10 additions & 22 deletions flow/layers/layer_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ namespace flutter {

class LayerTree {
public:
LayerTree(const SkISize& frame_size, float device_pixel_ratio);
struct Config {
std::shared_ptr<Layer> root_layer;
uint32_t rasterizer_tracing_threshold = 0;
bool checkerboard_raster_cache_images = false;
bool checkerboard_offscreen_layers = false;
};

LayerTree(const Config& config, const SkISize& frame_size);

// Perform a preroll pass on the tree and return information about
// the tree that affects rendering this frame.
Expand All @@ -50,36 +57,18 @@ class LayerTree {
GrDirectContext* gr_context = nullptr);

Layer* root_layer() const { return root_layer_.get(); }

void set_root_layer(std::shared_ptr<Layer> root_layer) {
root_layer_ = std::move(root_layer);
}

const SkISize& frame_size() const { return frame_size_; }
float device_pixel_ratio() const { return device_pixel_ratio_; }

const PaintRegionMap& paint_region_map() const { return paint_region_map_; }
PaintRegionMap& paint_region_map() { return paint_region_map_; }

// 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_threshold_ = interval;
}

// trace the rasterized picture to a trace file. 0 stands for disabling all
// tracing.
uint32_t rasterizer_tracing_threshold() const {
return rasterizer_tracing_threshold_;
}

void set_checkerboard_raster_cache_images(bool checkerboard) {
checkerboard_raster_cache_images_ = checkerboard;
}

void set_checkerboard_offscreen_layers(bool checkerboard) {
checkerboard_offscreen_layers_ = checkerboard;
}

/// When `Paint` is called, if leaf layer tracing is enabled, additional
/// metadata around raterization of leaf layers is collected.
///
Expand All @@ -95,7 +84,6 @@ class LayerTree {
private:
std::shared_ptr<Layer> root_layer_;
SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels.
const float device_pixel_ratio_; // Logical / Physical pixels ratio.
uint32_t rasterizer_tracing_threshold_;
bool checkerboard_raster_cache_images_;
bool checkerboard_offscreen_layers_;
Expand Down
55 changes: 34 additions & 21 deletions flow/layers/layer_tree_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ namespace testing {
class LayerTreeTest : public CanvasTest {
public:
LayerTreeTest()
: layer_tree_(SkISize::Make(64, 64), 1.0f),
root_transform_(SkMatrix::Translate(1.0f, 1.0f)),
: root_transform_(SkMatrix::Translate(1.0f, 1.0f)),
scoped_frame_(compositor_context_.AcquireFrame(nullptr,
&mock_canvas(),
nullptr,
Expand All @@ -31,12 +30,14 @@ class LayerTreeTest : public CanvasTest {
nullptr,
nullptr)) {}

LayerTree& layer_tree() { return layer_tree_; }
CompositorContext::ScopedFrame& frame() { return *scoped_frame_.get(); }
const SkMatrix& root_transform() { return root_transform_; }

std::unique_ptr<LayerTree> BuildLayerTree(const LayerTree::Config& config) {
return std::make_unique<LayerTree>(config, SkISize::Make(64, 64));
}

private:
LayerTree layer_tree_;
CompositorContext compositor_context_;
SkMatrix root_transform_;
std::unique_ptr<CompositorContext::ScopedFrame> scoped_frame_;
Expand All @@ -45,12 +46,14 @@ class LayerTreeTest : public CanvasTest {
TEST_F(LayerTreeTest, PaintingEmptyLayerDies) {
auto layer = std::make_shared<ContainerLayer>();

layer_tree().set_root_layer(layer);
layer_tree().Preroll(frame());
auto layer_tree = BuildLayerTree(LayerTree::Config{
.root_layer = layer,
});
layer_tree->Preroll(frame());
EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
EXPECT_TRUE(layer->is_empty());

layer_tree().Paint(frame());
layer_tree->Paint(frame());
}

TEST_F(LayerTreeTest, PaintBeforePrerollDies) {
Expand All @@ -61,13 +64,15 @@ TEST_F(LayerTreeTest, PaintBeforePrerollDies) {
auto layer = std::make_shared<ContainerLayer>();
layer->Add(mock_layer);

layer_tree().set_root_layer(layer);
auto layer_tree = BuildLayerTree(LayerTree::Config{
.root_layer = layer,
});
EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect);
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
EXPECT_TRUE(mock_layer->is_empty());
EXPECT_TRUE(layer->is_empty());

layer_tree().Paint(frame());
layer_tree->Paint(frame());
EXPECT_EQ(mock_canvas().draw_calls(), std::vector<MockCanvas::DrawCall>());
}

Expand All @@ -79,15 +84,17 @@ TEST_F(LayerTreeTest, Simple) {
auto layer = std::make_shared<ContainerLayer>();
layer->Add(mock_layer);

layer_tree().set_root_layer(layer);
layer_tree().Preroll(frame());
auto layer_tree = BuildLayerTree(LayerTree::Config{
.root_layer = layer,
});
layer_tree->Preroll(frame());
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
EXPECT_FALSE(mock_layer->is_empty());
EXPECT_FALSE(layer->is_empty());
EXPECT_EQ(mock_layer->parent_matrix(), root_transform());

layer_tree().Paint(frame());
layer_tree->Paint(frame());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::DrawPathData{child_path, child_paint}}}));
Expand All @@ -107,8 +114,10 @@ TEST_F(LayerTreeTest, Multiple) {

SkRect expected_total_bounds = child_path1.getBounds();
expected_total_bounds.join(child_path2.getBounds());
layer_tree().set_root_layer(layer);
layer_tree().Preroll(frame());
auto layer_tree = BuildLayerTree(LayerTree::Config{
.root_layer = layer,
});
layer_tree->Preroll(frame());
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
Expand All @@ -121,7 +130,7 @@ TEST_F(LayerTreeTest, Multiple) {
EXPECT_EQ(mock_layer2->parent_cull_rect(),
kGiantRect); // Siblings are independent

layer_tree().Paint(frame());
layer_tree->Paint(frame());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
Expand All @@ -140,8 +149,10 @@ TEST_F(LayerTreeTest, MultipleWithEmpty) {
layer->Add(mock_layer1);
layer->Add(mock_layer2);

layer_tree().set_root_layer(layer);
layer_tree().Preroll(frame());
auto layer_tree = BuildLayerTree(LayerTree::Config{
.root_layer = layer,
});
layer_tree->Preroll(frame());
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds());
EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds());
Expand All @@ -153,7 +164,7 @@ TEST_F(LayerTreeTest, MultipleWithEmpty) {
EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);

layer_tree().Paint(frame());
layer_tree->Paint(frame());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::DrawPathData{child_path1, child_paint1}}}));
Expand All @@ -172,8 +183,10 @@ TEST_F(LayerTreeTest, NeedsSystemComposite) {

SkRect expected_total_bounds = child_path1.getBounds();
expected_total_bounds.join(child_path2.getBounds());
layer_tree().set_root_layer(layer);
layer_tree().Preroll(frame());
auto layer_tree = BuildLayerTree(LayerTree::Config{
.root_layer = layer,
});
layer_tree->Preroll(frame());
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
Expand All @@ -185,7 +198,7 @@ TEST_F(LayerTreeTest, NeedsSystemComposite) {
EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);

layer_tree().Paint(frame());
layer_tree->Paint(frame());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
Expand Down
71 changes: 38 additions & 33 deletions lib/ui/compositing/scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,22 @@ Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers) {
// Currently only supports a single window.
auto viewport_metrics = UIDartState::Current()
->platform_configuration()
->get_window(0)
->viewport_metrics();

layer_tree_ = std::make_shared<LayerTree>(
SkISize::Make(viewport_metrics.physical_width,
viewport_metrics.physical_height),
static_cast<float>(viewport_metrics.device_pixel_ratio));
layer_tree_->set_root_layer(std::move(rootLayer));
layer_tree_->set_rasterizer_tracing_threshold(rasterizerTracingThreshold);
layer_tree_->set_checkerboard_raster_cache_images(
checkerboardRasterCacheImages);
layer_tree_->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers);
layer_tree_config_.root_layer = std::move(rootLayer);
layer_tree_config_.rasterizer_tracing_threshold = rasterizerTracingThreshold;
layer_tree_config_.checkerboard_raster_cache_images =
checkerboardRasterCacheImages;
layer_tree_config_.checkerboard_offscreen_layers =
checkerboardOffscreenLayers;
}

Scene::~Scene() {}

bool Scene::valid() {
return layer_tree_config_.root_layer != nullptr;
}

void Scene::dispose() {
layer_tree_.reset();
layer_tree_config_.root_layer.reset();
ClearDartWrapper();
}

Expand All @@ -69,8 +64,8 @@ Dart_Handle Scene::toImageSync(uint32_t width,
Dart_Handle raw_image_handle) {
TRACE_EVENT0("flutter", "Scene::toImageSync");

if (!layer_tree_) {
return tonic::ToDart("Scene did not contain a layer tree.");
if (!valid()) {
return tonic::ToDart("Scene has been disposed.");
}

Scene::RasterizeToImage(width, height, raw_image_handle);
Expand All @@ -82,32 +77,32 @@ Dart_Handle Scene::toImage(uint32_t width,
Dart_Handle raw_image_callback) {
TRACE_EVENT0("flutter", "Scene::toImage");

if (!layer_tree_) {
return tonic::ToDart("Scene did not contain a layer tree.");
if (!valid()) {
return tonic::ToDart("Scene has been disposed.");
}

return Picture::RasterizeLayerTreeToImage(std::move(layer_tree_), width,
height, raw_image_callback);
return Picture::RasterizeLayerTreeToImage(BuildLayerTree(width, height),
raw_image_callback);
}

static sk_sp<DlImage> CreateDeferredImage(
bool impeller,
std::shared_ptr<LayerTree> layer_tree,
uint32_t width,
uint32_t height,
std::unique_ptr<LayerTree> layer_tree,
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
#if IMPELLER_SUPPORTS_RENDERING
if (impeller) {
return DlDeferredImageGPUImpeller::Make(
std::move(layer_tree), SkISize::Make(width, height),
std::move(snapshot_delegate), std::move(raster_task_runner));
return DlDeferredImageGPUImpeller::Make(std::move(layer_tree),
std::move(snapshot_delegate),
std::move(raster_task_runner));
}
#endif // IMPELLER_SUPPORTS_RENDERING

const SkImageInfo image_info = SkImageInfo::Make(
width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
const auto& frame_size = layer_tree->frame_size();
const SkImageInfo image_info =
SkImageInfo::Make(frame_size.width(), frame_size.height(),
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
return DlDeferredImageGPUSkia::MakeFromLayerTree(
image_info, std::move(layer_tree), std::move(snapshot_delegate),
raster_task_runner, std::move(unref_queue));
Expand All @@ -126,15 +121,25 @@ void Scene::RasterizeToImage(uint32_t width,

auto image = CanvasImage::Create();
auto dl_image = CreateDeferredImage(
dart_state->IsImpellerEnabled(), layer_tree_, width, height,
dart_state->IsImpellerEnabled(), BuildLayerTree(width, height),
std::move(snapshot_delegate), std::move(raster_task_runner),
std::move(unref_queue));
image->set_image(dl_image);
image->AssociateWithDartWrapper(raw_image_handle);
}

std::shared_ptr<flutter::LayerTree> Scene::takeLayerTree() {
return std::move(layer_tree_);
std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree(uint64_t width,
uint64_t height) {
return BuildLayerTree(width, height);
}

std::unique_ptr<LayerTree> Scene::BuildLayerTree(uint32_t width,
uint32_t height) {
if (!valid()) {
return nullptr;
}
return std::make_unique<LayerTree>(layer_tree_config_,
SkISize::Make(width, height));
}

} // namespace flutter
15 changes: 8 additions & 7 deletions lib/ui/compositing/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class Scene : public RefCountedDartWrappable<Scene> {
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers);

std::shared_ptr<flutter::LayerTree> takeLayerTree();
std::unique_ptr<flutter::LayerTree> takeLayerTree(uint64_t width,
uint64_t height);

Dart_Handle toImageSync(uint32_t width,
uint32_t height,
Expand All @@ -44,16 +45,16 @@ class Scene : public RefCountedDartWrappable<Scene> {
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers);

// Returns true if `dispose()` has not been called.
bool valid();

void RasterizeToImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle);

// This is a shared_ptr to support flattening the layer tree from the UI
// thread onto the raster thread - allowing access to the texture registry
// required to render TextureLayers.
//
// No longer valid after calling `takeLayerTree`.
std::shared_ptr<flutter::LayerTree> layer_tree_;
std::unique_ptr<LayerTree> BuildLayerTree(uint32_t width, uint32_t height);

flutter::LayerTree::Config layer_tree_config_;
};

} // namespace flutter
Expand Down
Loading