mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
At a quick glance, one could easily think of the "engine_time" as the GPU thread time and the "frame_time" as the UI thread time because the GPU thread time is mainly spent on the engine while the UI thread time is mainly spent on the Dart framework to generate the frame. But it's actually the other way. The "engine_time" is UI thread time and the "frame_time" is the GPU thread time. To avoid the confusion, rename them to "ui_time" and "raster_time" respectively. I avoided the "gpu_time" because the rasterization may be purely on a CPU backed software Skia backend.
154 lines
5.4 KiB
C++
154 lines
5.4 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()
|
|
: frame_size_{},
|
|
rasterizer_tracing_threshold_(0),
|
|
checkerboard_raster_cache_images_(false),
|
|
checkerboard_offscreen_layers_(false) {}
|
|
|
|
LayerTree::~LayerTree() = default;
|
|
|
|
void LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
|
|
bool ignore_raster_cache) {
|
|
TRACE_EVENT0("flutter", "LayerTree::Preroll");
|
|
SkColorSpace* color_space =
|
|
frame.canvas() ? frame.canvas()->imageInfo().colorSpace() : nullptr;
|
|
frame.context().raster_cache().SetCheckboardCacheImages(
|
|
checkerboard_raster_cache_images_);
|
|
PrerollContext context = {
|
|
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
|
|
frame.gr_context(),
|
|
frame.view_embedder(),
|
|
color_space,
|
|
kGiantRect,
|
|
frame.context().raster_time(),
|
|
frame.context().ui_time(),
|
|
frame.context().texture_registry(),
|
|
checkerboard_offscreen_layers_};
|
|
|
|
root_layer_->Preroll(&context, frame.root_surface_transformation());
|
|
}
|
|
|
|
#if defined(OS_FUCHSIA)
|
|
void LayerTree::UpdateScene(SceneUpdateContext& context,
|
|
scenic::ContainerNode& container) {
|
|
TRACE_EVENT0("flutter", "LayerTree::UpdateScene");
|
|
const auto& metrics = context.metrics();
|
|
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);
|
|
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");
|
|
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_};
|
|
|
|
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;
|
|
}
|
|
|
|
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
|
|
nullptr, // SkColorSpace* dst_color_space
|
|
kGiantRect, // SkRect cull_rect
|
|
unused_stopwatch, // frame time (dont care)
|
|
unused_stopwatch, // engine time (dont care)
|
|
unused_texture_registry, // texture registry (not supported)
|
|
false, // checkerboard_offscreen_layers
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
// 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
|