flutter_flutter/flow/layers/layer_tree.cc
mikejurka ad8ccf47b1
[Fuchsia] Move physical shape layer compositing to Flutter (#17005)
* [fuchsia] Add labels to Scenic nodes.

* [fuchsia] Skip creating Scenic nodes for identity Transforms.

* [fuchsia] Assign elevation to Scenic nodes based on paint order.

* [fuchsia] Create Scenic OpacityNodes at leaf nodes.

* [fuchsia] Composite PhysicalShapeLayers using Skia, except when they need to float above child views.

In that case, they will still need to be pulled
into separate Scenic nodes to be composited on top
of the child view[s].

* [fuchsia] Add tests for Fuchsia-specific layer behavior.

Inspect commands going to Scenic and make sure
they match what is expected.

Also, restructure code to need less member variables,
and other cleanups based on review feedback.
2020-03-23 16:38:07 -07:00

198 lines
6.9 KiB
C++

// Copyright 2013 The Flutter 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/layers/layer_tree.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"
namespace flutter {
LayerTree::LayerTree(const SkISize& frame_size,
float frame_physical_depth,
float frame_device_pixel_ratio)
: frame_size_(frame_size),
frame_physical_depth_(frame_physical_depth),
frame_device_pixel_ratio_(frame_device_pixel_ratio),
rasterizer_tracing_threshold_(0),
checkerboard_raster_cache_images_(false),
checkerboard_offscreen_layers_(false) {}
void LayerTree::RecordBuildTime(fml::TimePoint start) {
build_start_ = start;
build_finish_ = fml::TimePoint::Now();
}
bool LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
bool ignore_raster_cache) {
TRACE_EVENT0("flutter", "LayerTree::Preroll");
if (!root_layer_) {
FML_LOG(ERROR) << "The scene did not specify any layers.";
return false;
}
SkColorSpace* color_space =
frame.canvas() ? frame.canvas()->imageInfo().colorSpace() : nullptr;
frame.context().raster_cache().SetCheckboardCacheImages(
checkerboard_raster_cache_images_);
MutatorsStack stack;
PrerollContext context = {
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
frame.gr_context(),
frame.view_embedder(),
stack,
color_space,
kGiantRect,
false,
frame.context().raster_time(),
frame.context().ui_time(),
frame.context().texture_registry(),
checkerboard_offscreen_layers_,
frame_physical_depth_,
frame_device_pixel_ratio_};
root_layer_->Preroll(&context, frame.root_surface_transformation());
return context.surface_needs_readback;
}
#if defined(OS_FUCHSIA)
void LayerTree::UpdateScene(SceneUpdateContext& context,
scenic::ContainerNode& container) {
TRACE_EVENT0("flutter", "LayerTree::UpdateScene");
// Ensure the context is aware of the view metrics.
context.set_dimensions(frame_size_, frame_physical_depth_,
frame_device_pixel_ratio_);
const auto& metrics = context.metrics();
FML_DCHECK(metrics->scale_x > 0.0f);
FML_DCHECK(metrics->scale_y > 0.0f);
FML_DCHECK(metrics->scale_z > 0.0f);
SceneUpdateContext::Transform transform(context, // context
1.0f / metrics->scale_x, // X
1.0f / metrics->scale_y, // Y
1.0f / metrics->scale_z // Z
);
SceneUpdateContext::Frame frame(
context,
SkRRect::MakeRect(
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
SK_ColorTRANSPARENT, SK_AlphaOPAQUE, "flutter::LayerTree");
if (root_layer_->needs_system_composite()) {
root_layer_->UpdateScene(context);
}
if (root_layer_->needs_painting()) {
frame.AddPaintLayer(root_layer_.get());
}
container.AddChild(transform.entity_node());
}
#endif
void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
bool ignore_raster_cache) const {
TRACE_EVENT0("flutter", "LayerTree::Paint");
if (!root_layer_) {
FML_LOG(ERROR) << "The scene did not specify any layers to paint.";
return;
}
SkISize canvas_size = frame.canvas()->getBaseLayerSize();
SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height());
internal_nodes_canvas.addCanvas(frame.canvas());
if (frame.view_embedder() != nullptr) {
auto overlay_canvases = frame.view_embedder()->GetCurrentCanvases();
for (size_t i = 0; i < overlay_canvases.size(); i++) {
internal_nodes_canvas.addCanvas(overlay_canvases[i]);
}
}
Layer::PaintContext context = {
(SkCanvas*)&internal_nodes_canvas,
frame.canvas(),
frame.gr_context(),
frame.view_embedder(),
frame.context().raster_time(),
frame.context().ui_time(),
frame.context().texture_registry(),
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
checkerboard_offscreen_layers_,
frame_physical_depth_,
frame_device_pixel_ratio_};
if (root_layer_->needs_painting())
root_layer_->Paint(context);
}
sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
TRACE_EVENT0("flutter", "LayerTree::Flatten");
SkPictureRecorder recorder;
auto* canvas = recorder.beginRecording(bounds);
if (!canvas) {
return nullptr;
}
MutatorsStack unused_stack;
const Stopwatch unused_stopwatch;
TextureRegistry unused_texture_registry;
SkMatrix root_surface_transformation;
// No root surface transformation. So assume identity.
root_surface_transformation.reset();
PrerollContext preroll_context{
nullptr, // raster_cache (don't consult the cache)
nullptr, // gr_context (used for the raster cache)
nullptr, // external view embedder
unused_stack, // mutator stack
nullptr, // SkColorSpace* dst_color_space
kGiantRect, // SkRect cull_rect
false, // layer reads from surface
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
false, // checkerboard_offscreen_layers
frame_physical_depth_, // maximum depth allowed for rendering
frame_device_pixel_ratio_ // ratio between logical and physical
};
SkISize canvas_size = canvas->getBaseLayerSize();
SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height());
internal_nodes_canvas.addCanvas(canvas);
Layer::PaintContext paint_context = {
(SkCanvas*)&internal_nodes_canvas,
canvas, // canvas
nullptr,
nullptr,
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
nullptr, // raster cache
false, // checkerboard offscreen layers
frame_physical_depth_, // maximum depth allowed for rendering
frame_device_pixel_ratio_ // ratio between logical and physical
};
// Even if we don't have a root layer, we still need to create an empty
// picture.
if (root_layer_) {
root_layer_->Preroll(&preroll_context, root_surface_transformation);
// The needs painting flag may be set after the preroll. So check it after.
if (root_layer_->needs_painting()) {
root_layer_->Paint(paint_context);
}
}
return recorder.finishRecordingAsPicture();
}
} // namespace flutter