mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland Wire up Opacity on Fuchsia (#14559)
This reverts commit 6ea69a0d4339dd153899bb6c299689f1dd43329d. On top of the revert, it reverted a commit in the PR: https://github.com/flutter/engine/pull/14024 This reverts commit ea67e5b0b930ebf552bc7dbd678a35ee6a129c39.
This commit is contained in:
parent
9c1bd8aee6
commit
f2dbeb8aa7
@ -48,6 +48,10 @@ FILE: ../../../flutter/flow/layers/color_filter_layer_unittests.cc
|
||||
FILE: ../../../flutter/flow/layers/container_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/container_layer.h
|
||||
FILE: ../../../flutter/flow/layers/container_layer_unittests.cc
|
||||
FILE: ../../../flutter/flow/layers/elevated_container_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/elevated_container_layer.h
|
||||
FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.h
|
||||
FILE: ../../../flutter/flow/layers/layer.cc
|
||||
FILE: ../../../flutter/flow/layers/layer.h
|
||||
FILE: ../../../flutter/flow/layers/layer_tree.cc
|
||||
|
||||
@ -28,6 +28,8 @@ source_set("flow") {
|
||||
"layers/color_filter_layer.h",
|
||||
"layers/container_layer.cc",
|
||||
"layers/container_layer.h",
|
||||
"layers/elevated_container_layer.cc",
|
||||
"layers/elevated_container_layer.h",
|
||||
"layers/layer.cc",
|
||||
"layers/layer.h",
|
||||
"layers/layer_tree.cc",
|
||||
@ -76,6 +78,8 @@ source_set("flow") {
|
||||
sources += [
|
||||
"layers/child_scene_layer.cc",
|
||||
"layers/child_scene_layer.h",
|
||||
"layers/fuchsia_system_composited_layer.cc",
|
||||
"layers/fuchsia_system_composited_layer.h",
|
||||
"scene_update_context.cc",
|
||||
"scene_update_context.h",
|
||||
"view_holder.cc",
|
||||
|
||||
@ -9,8 +9,7 @@ namespace flutter {
|
||||
ContainerLayer::ContainerLayer() {}
|
||||
|
||||
void ContainerLayer::Add(std::shared_ptr<Layer> layer) {
|
||||
layer->set_parent(this);
|
||||
layers_.push_back(std::move(layer));
|
||||
layers_.emplace_back(std::move(layer));
|
||||
}
|
||||
|
||||
void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
|
||||
@ -14,7 +14,7 @@ class ContainerLayer : public Layer {
|
||||
public:
|
||||
ContainerLayer();
|
||||
|
||||
void Add(std::shared_ptr<Layer> layer);
|
||||
virtual void Add(std::shared_ptr<Layer> layer);
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext& context) const override;
|
||||
|
||||
49
flow/layers/elevated_container_layer.cc
Normal file
49
flow/layers/elevated_container_layer.cc
Normal file
@ -0,0 +1,49 @@
|
||||
// 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/elevated_container_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace {
|
||||
|
||||
float ClampElevation(float elevation,
|
||||
float parent_elevation,
|
||||
float max_elevation) {
|
||||
// TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be
|
||||
// able to have developers specify the behavior here to alternatives besides
|
||||
// clamping, like normalization on some arbitrary curve.
|
||||
float clamped_elevation = elevation;
|
||||
if (max_elevation > -1 && (parent_elevation + elevation) > max_elevation) {
|
||||
// Clamp the local z coordinate at our max bound. Take into account the
|
||||
// parent z position here to fix clamping in cases where the child is
|
||||
// overflowing because of its parents.
|
||||
clamped_elevation = max_elevation - parent_elevation;
|
||||
}
|
||||
|
||||
return clamped_elevation;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ElevatedContainerLayer::ElevatedContainerLayer(float elevation)
|
||||
: elevation_(elevation), clamped_elevation_(elevation) {}
|
||||
|
||||
void ElevatedContainerLayer::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "ElevatedContainerLayer::Preroll");
|
||||
|
||||
// Track total elevation as we walk the tree, in order to deal with bounds
|
||||
// overflow in z.
|
||||
parent_elevation_ = context->total_elevation;
|
||||
clamped_elevation_ = ClampElevation(elevation_, parent_elevation_,
|
||||
context->frame_physical_depth);
|
||||
context->total_elevation += clamped_elevation_;
|
||||
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
|
||||
// Restore the elevation for our parent.
|
||||
context->total_elevation = parent_elevation_;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
34
flow/layers/elevated_container_layer.h
Normal file
34
flow/layers/elevated_container_layer.h
Normal file
@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
#ifndef FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class ElevatedContainerLayer : public ContainerLayer {
|
||||
public:
|
||||
ElevatedContainerLayer(float elevation);
|
||||
~ElevatedContainerLayer() override = default;
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
float elevation() const { return clamped_elevation_; }
|
||||
float total_elevation() const {
|
||||
return parent_elevation_ + clamped_elevation_;
|
||||
}
|
||||
|
||||
private:
|
||||
float parent_elevation_ = 0.0f;
|
||||
float elevation_ = 0.0f;
|
||||
float clamped_elevation_ = 0.0f;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ElevatedContainerLayer);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
|
||||
41
flow/layers/fuchsia_system_composited_layer.cc
Normal file
41
flow/layers/fuchsia_system_composited_layer.cc
Normal file
@ -0,0 +1,41 @@
|
||||
// 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/fuchsia_system_composited_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
FuchsiaSystemCompositedLayer::FuchsiaSystemCompositedLayer(SkColor color,
|
||||
float elevation)
|
||||
: ElevatedContainerLayer(elevation), color_(color) {}
|
||||
|
||||
void FuchsiaSystemCompositedLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
// Retained rendering: speedup by reusing a retained entity node if
|
||||
// possible. When an entity node is reused, no paint layer is added to the
|
||||
// frame so we won't call Paint.
|
||||
LayerRasterCacheKey key(unique_id(), context.Matrix());
|
||||
if (context.HasRetainedNode(key)) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
|
||||
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
|
||||
FML_DCHECK(context.top_entity());
|
||||
FML_DCHECK(retained_node.session() == context.session());
|
||||
context.top_entity()->embedder_node().AddChild(retained_node);
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_EVENT_INSTANT0("flutter", "retained cache miss, creating");
|
||||
// If we can't find an existing retained surface, create one.
|
||||
SceneUpdateContext::Frame frame(context, rrect_, color_, elevation(), this);
|
||||
for (auto& layer : layers()) {
|
||||
if (layer->needs_painting()) {
|
||||
frame.AddPaintLayer(layer.get());
|
||||
}
|
||||
}
|
||||
|
||||
ContainerLayer::UpdateScene(context);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
34
flow/layers/fuchsia_system_composited_layer.h
Normal file
34
flow/layers/fuchsia_system_composited_layer.h
Normal file
@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
#ifndef FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
#include "flutter/flow/scene_update_context.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class FuchsiaSystemCompositedLayer : public ElevatedContainerLayer {
|
||||
public:
|
||||
static bool can_system_composite() { return true; }
|
||||
|
||||
FuchsiaSystemCompositedLayer(SkColor color, float elevation);
|
||||
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
|
||||
void set_dimensions(SkRRect rrect) { rrect_ = rrect; }
|
||||
|
||||
SkColor color() const { return color_; }
|
||||
|
||||
private:
|
||||
SkRRect rrect_ = SkRRect::MakeEmpty();
|
||||
SkColor color_ = SK_ColorTRANSPARENT;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaSystemCompositedLayer);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
|
||||
@ -10,10 +10,9 @@
|
||||
namespace flutter {
|
||||
|
||||
Layer::Layer()
|
||||
: parent_(nullptr),
|
||||
needs_system_composite_(false),
|
||||
paint_bounds_(SkRect::MakeEmpty()),
|
||||
unique_id_(NextUniqueID()) {}
|
||||
: paint_bounds_(SkRect::MakeEmpty()),
|
||||
unique_id_(NextUniqueID()),
|
||||
needs_system_composite_(false) {}
|
||||
|
||||
Layer::~Layer() = default;
|
||||
|
||||
|
||||
@ -42,8 +42,6 @@ static constexpr SkRect kGiantRect = SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
|
||||
// This should be an exact copy of the Clip enum in painting.dart.
|
||||
enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer };
|
||||
|
||||
class ContainerLayer;
|
||||
|
||||
struct PrerollContext {
|
||||
RasterCache* raster_cache;
|
||||
GrContext* gr_context;
|
||||
@ -53,11 +51,18 @@ struct PrerollContext {
|
||||
SkRect cull_rect;
|
||||
bool surface_needs_readback;
|
||||
|
||||
// The following allows us to paint in the end of subtree preroll
|
||||
// These allow us to paint in the end of subtree Preroll.
|
||||
const Stopwatch& raster_time;
|
||||
const Stopwatch& ui_time;
|
||||
TextureRegistry& texture_registry;
|
||||
const bool checkerboard_offscreen_layers;
|
||||
|
||||
// These allow us to make use of the scene metrics during Preroll.
|
||||
float frame_physical_depth;
|
||||
float frame_device_pixel_ratio;
|
||||
|
||||
// These allow us to track properties like elevation and opacity which stack
|
||||
// with each other during Preroll.
|
||||
float total_elevation = 0.0f;
|
||||
bool has_platform_view = false;
|
||||
};
|
||||
@ -117,6 +122,10 @@ class Layer {
|
||||
TextureRegistry& texture_registry;
|
||||
const RasterCache* raster_cache;
|
||||
const bool checkerboard_offscreen_layers;
|
||||
|
||||
// These allow us to make use of the scene metrics during Paint.
|
||||
float frame_physical_depth;
|
||||
float frame_device_pixel_ratio;
|
||||
};
|
||||
|
||||
// Calls SkCanvas::saveLayer and restores the layer upon destruction. Also
|
||||
@ -153,10 +162,6 @@ class Layer {
|
||||
virtual void UpdateScene(SceneUpdateContext& context);
|
||||
#endif
|
||||
|
||||
ContainerLayer* parent() const { return parent_; }
|
||||
|
||||
void set_parent(ContainerLayer* parent) { parent_ = parent; }
|
||||
|
||||
bool needs_system_composite() const { return needs_system_composite_; }
|
||||
void set_needs_system_composite(bool value) {
|
||||
needs_system_composite_ = value;
|
||||
@ -175,10 +180,9 @@ class Layer {
|
||||
uint64_t unique_id() const { return unique_id_; }
|
||||
|
||||
private:
|
||||
ContainerLayer* parent_;
|
||||
bool needs_system_composite_;
|
||||
SkRect paint_bounds_;
|
||||
uint64_t unique_id_;
|
||||
bool needs_system_composite_;
|
||||
|
||||
static uint64_t NextUniqueID();
|
||||
|
||||
|
||||
@ -11,8 +11,12 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
LayerTree::LayerTree()
|
||||
: frame_size_{},
|
||||
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) {}
|
||||
@ -47,7 +51,9 @@ bool LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
|
||||
frame.context().raster_time(),
|
||||
frame.context().ui_time(),
|
||||
frame.context().texture_registry(),
|
||||
checkerboard_offscreen_layers_};
|
||||
checkerboard_offscreen_layers_,
|
||||
frame_physical_depth_,
|
||||
frame_device_pixel_ratio_};
|
||||
|
||||
root_layer_->Preroll(&context, frame.root_surface_transformation());
|
||||
return context.surface_needs_readback;
|
||||
@ -57,12 +63,22 @@ bool LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
|
||||
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(
|
||||
@ -106,7 +122,9 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
|
||||
frame.context().ui_time(),
|
||||
frame.context().texture_registry(),
|
||||
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
|
||||
checkerboard_offscreen_layers_};
|
||||
checkerboard_offscreen_layers_,
|
||||
frame_physical_depth_,
|
||||
frame_device_pixel_ratio_};
|
||||
|
||||
if (root_layer_->needs_painting())
|
||||
root_layer_->Paint(context);
|
||||
@ -130,17 +148,19 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
|
||||
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
|
||||
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();
|
||||
@ -152,11 +172,13 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
|
||||
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
|
||||
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
|
||||
|
||||
@ -14,13 +14,14 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/time/time_delta.h"
|
||||
#include "third_party/skia/include/core/SkPicture.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class LayerTree {
|
||||
public:
|
||||
LayerTree();
|
||||
LayerTree(const SkISize& frame_size,
|
||||
float frame_physical_depth,
|
||||
float frame_device_pixel_ratio);
|
||||
|
||||
// Perform a preroll pass on the tree and return information about
|
||||
// the tree that affects rendering this frame.
|
||||
@ -49,8 +50,8 @@ class LayerTree {
|
||||
}
|
||||
|
||||
const SkISize& frame_size() const { return frame_size_; }
|
||||
|
||||
void set_frame_size(const SkISize& frame_size) { frame_size_ = frame_size; }
|
||||
float frame_physical_depth() const { return frame_physical_depth_; }
|
||||
float frame_device_pixel_ratio() const { return frame_device_pixel_ratio_; }
|
||||
|
||||
void RecordBuildTime(fml::TimePoint begin_start);
|
||||
fml::TimePoint build_start() const { return build_start_; }
|
||||
@ -76,18 +77,15 @@ class LayerTree {
|
||||
checkerboard_offscreen_layers_ = checkerboard;
|
||||
}
|
||||
|
||||
void set_device_pixel_ratio(double device_pixel_ratio) {
|
||||
device_pixel_ratio_ = device_pixel_ratio;
|
||||
}
|
||||
|
||||
double device_pixel_ratio() const { return device_pixel_ratio_; }
|
||||
double device_pixel_ratio() const { return frame_device_pixel_ratio_; }
|
||||
|
||||
private:
|
||||
SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels.
|
||||
double device_pixel_ratio_ = 1.0;
|
||||
std::shared_ptr<Layer> root_layer_;
|
||||
fml::TimePoint build_start_;
|
||||
fml::TimePoint build_finish_;
|
||||
SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels.
|
||||
float frame_physical_depth_;
|
||||
float frame_device_pixel_ratio_ = 1.0f; // Logical / Physical pixels ratio.
|
||||
uint32_t rasterizer_tracing_threshold_;
|
||||
bool checkerboard_raster_cache_images_;
|
||||
bool checkerboard_offscreen_layers_;
|
||||
|
||||
@ -17,14 +17,17 @@ namespace testing {
|
||||
|
||||
class LayerTreeTest : public CanvasTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
root_transform_ = SkMatrix::MakeTrans(1.0f, 1.0f);
|
||||
scoped_frame_ =
|
||||
compositor_context_.AcquireFrame(nullptr, &mock_canvas(), nullptr,
|
||||
root_transform_, false, true, nullptr);
|
||||
}
|
||||
|
||||
void TearDown() override { scoped_frame_ = nullptr; }
|
||||
LayerTreeTest()
|
||||
: layer_tree_(SkISize::Make(64, 64), 100.0f, 1.0f),
|
||||
compositor_context_(fml::kDefaultFrameBudget),
|
||||
root_transform_(SkMatrix::MakeTrans(1.0f, 1.0f)),
|
||||
scoped_frame_(compositor_context_.AcquireFrame(nullptr,
|
||||
&mock_canvas(),
|
||||
nullptr,
|
||||
root_transform_,
|
||||
false,
|
||||
true,
|
||||
nullptr)) {}
|
||||
|
||||
LayerTree& layer_tree() { return layer_tree_; }
|
||||
CompositorContext::ScopedFrame& frame() { return *scoped_frame_.get(); }
|
||||
|
||||
@ -4,36 +4,33 @@
|
||||
|
||||
#include "flutter/flow/layers/opacity_layer.h"
|
||||
|
||||
#include "flutter/flow/layers/transform_layer.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "third_party/skia/include/core/SkPaint.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
OpacityLayer::OpacityLayer(int alpha, const SkPoint& offset)
|
||||
: alpha_(alpha), offset_(offset) {}
|
||||
: alpha_(alpha), offset_(offset) {
|
||||
// Ensure OpacityLayer has only one direct child.
|
||||
//
|
||||
// This is needed to ensure that retained rendering can always be applied to
|
||||
// save the costly saveLayer.
|
||||
//
|
||||
// Any children will be actually added as children of this empty
|
||||
// ContainerLayer.
|
||||
ContainerLayer::Add(std::make_shared<ContainerLayer>());
|
||||
}
|
||||
|
||||
void OpacityLayer::EnsureSingleChild() {
|
||||
FML_DCHECK(layers().size() > 0); // OpacityLayer should never be a leaf
|
||||
|
||||
if (layers().size() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Be careful: SkMatrix's default constructor doesn't initialize the matrix to
|
||||
// identity. Hence we have to explicitly call SkMatrix::setIdentity.
|
||||
SkMatrix identity;
|
||||
identity.setIdentity();
|
||||
auto new_child = std::make_shared<flutter::TransformLayer>(identity);
|
||||
|
||||
for (auto& child : layers()) {
|
||||
new_child->Add(child);
|
||||
}
|
||||
ClearChildren();
|
||||
Add(new_child);
|
||||
void OpacityLayer::Add(std::shared_ptr<Layer> layer) {
|
||||
GetChildContainer()->Add(std::move(layer));
|
||||
}
|
||||
|
||||
void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "OpacityLayer::Preroll");
|
||||
EnsureSingleChild();
|
||||
|
||||
ContainerLayer* container = GetChildContainer();
|
||||
FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf.
|
||||
|
||||
SkMatrix child_matrix = matrix;
|
||||
child_matrix.postTranslate(offset_.fX, offset_.fY);
|
||||
context->mutators_stack.PushTransform(
|
||||
@ -45,16 +42,14 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
context->mutators_stack.Pop();
|
||||
context->mutators_stack.Pop();
|
||||
set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
|
||||
// See |EnsureSingleChild|.
|
||||
FML_DCHECK(layers().size() == 1);
|
||||
|
||||
if (!context->has_platform_view && context->raster_cache &&
|
||||
SkRect::Intersects(context->cull_rect, paint_bounds())) {
|
||||
Layer* child = layers()[0].get();
|
||||
SkMatrix ctm = child_matrix;
|
||||
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
|
||||
ctm = RasterCache::GetIntegralTransCTM(ctm);
|
||||
#endif
|
||||
context->raster_cache->Prepare(context, child, ctm);
|
||||
context->raster_cache->Prepare(context, container, ctm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,13 +68,10 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
context.leaf_nodes_canvas->getTotalMatrix()));
|
||||
#endif
|
||||
|
||||
// See |EnsureSingleChild|.
|
||||
FML_DCHECK(layers().size() == 1);
|
||||
|
||||
if (context.raster_cache) {
|
||||
ContainerLayer* container = GetChildContainer();
|
||||
const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix();
|
||||
RasterCacheResult child_cache =
|
||||
context.raster_cache->Get(layers()[0].get(), ctm);
|
||||
RasterCacheResult child_cache = context.raster_cache->Get(container, ctm);
|
||||
if (child_cache.is_valid()) {
|
||||
child_cache.draw(*context.leaf_nodes_canvas, &paint);
|
||||
return;
|
||||
@ -105,4 +97,10 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
PaintChildren(context);
|
||||
}
|
||||
|
||||
ContainerLayer* OpacityLayer::GetChildContainer() const {
|
||||
FML_DCHECK(layers().size() == 1);
|
||||
|
||||
return static_cast<ContainerLayer*>(layers()[0].get());
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -11,8 +11,8 @@ namespace flutter {
|
||||
|
||||
// Don't add an OpacityLayer with no children to the layer tree. Painting an
|
||||
// OpacityLayer is very costly due to the saveLayer call. If there's no child,
|
||||
// having the OpacityLayer or not has the same effect. In debug_unopt build, the
|
||||
// |EnsureSingleChild| will assert if there are no children.
|
||||
// having the OpacityLayer or not has the same effect. In debug_unopt build,
|
||||
// |Preroll| will assert if there are no children.
|
||||
class OpacityLayer : public ContainerLayer {
|
||||
public:
|
||||
// An offset is provided here because OpacityLayer.addToScene method in the
|
||||
@ -27,6 +27,8 @@ class OpacityLayer : public ContainerLayer {
|
||||
// the propagation as repainting the OpacityLayer is expensive.
|
||||
OpacityLayer(int alpha, const SkPoint& offset);
|
||||
|
||||
void Add(std::shared_ptr<Layer> layer) override;
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
void Paint(PaintContext& context) const override;
|
||||
@ -35,19 +37,11 @@ class OpacityLayer : public ContainerLayer {
|
||||
// session scene hierarchy.
|
||||
|
||||
private:
|
||||
ContainerLayer* GetChildContainer() const;
|
||||
|
||||
int alpha_;
|
||||
SkPoint offset_;
|
||||
|
||||
// Restructure (if necessary) OpacityLayer to have only one child.
|
||||
//
|
||||
// This is needed to ensure that retained rendering can always be applied to
|
||||
// save the costly saveLayer.
|
||||
//
|
||||
// If there are multiple children, this creates a new identity TransformLayer,
|
||||
// sets all children to be the TransformLayer's children, and sets that
|
||||
// TransformLayer as the single child of this OpacityLayer.
|
||||
void EnsureSingleChild();
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
|
||||
};
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ TEST_F(OpacityLayerTest, LeafLayer) {
|
||||
std::make_shared<OpacityLayer>(SK_AlphaOPAQUE, SkPoint::Make(0.0f, 0.0f));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()),
|
||||
"layers\\(\\)\\.size\\(\\) > 0");
|
||||
"\\!container->layers\\(\\)\\.empty\\(\\)");
|
||||
}
|
||||
|
||||
TEST_F(OpacityLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
@ -14,18 +14,11 @@ const SkScalar kLightRadius = 800;
|
||||
|
||||
PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
|
||||
SkColor shadow_color,
|
||||
SkScalar device_pixel_ratio,
|
||||
float viewport_depth,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior)
|
||||
: color_(color),
|
||||
: PhysicalShapeLayerBase(color, elevation),
|
||||
shadow_color_(shadow_color),
|
||||
device_pixel_ratio_(device_pixel_ratio),
|
||||
#if defined(OS_FUCHSIA)
|
||||
viewport_depth_(viewport_depth),
|
||||
#endif
|
||||
elevation_(elevation),
|
||||
path_(path),
|
||||
isRect_(false),
|
||||
clip_behavior_(clip_behavior) {
|
||||
@ -48,33 +41,35 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
|
||||
// an SkPath.
|
||||
frameRRect_ = SkRRect::MakeRect(path.getBounds());
|
||||
}
|
||||
|
||||
set_dimensions(frameRRect_);
|
||||
}
|
||||
|
||||
void PhysicalShapeLayer::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Preroll");
|
||||
|
||||
Layer::AutoPrerollSaveLayerState save =
|
||||
Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer());
|
||||
PhysicalShapeLayerBase::Preroll(context, matrix);
|
||||
|
||||
context->total_elevation += elevation_;
|
||||
total_elevation_ = context->total_elevation;
|
||||
SkRect child_paint_bounds;
|
||||
PrerollChildren(context, matrix, &child_paint_bounds);
|
||||
context->total_elevation -= elevation_;
|
||||
|
||||
if (elevation_ == 0) {
|
||||
if (elevation() == 0) {
|
||||
set_paint_bounds(path_.getBounds());
|
||||
} else {
|
||||
#if defined(OS_FUCHSIA)
|
||||
// Let the system compositor draw all shadows for us.
|
||||
set_needs_system_composite(true);
|
||||
#else
|
||||
if (PhysicalShapeLayerBase::can_system_composite()) {
|
||||
set_needs_system_composite(true);
|
||||
return;
|
||||
}
|
||||
//#if defined(OS_FUCHSIA)
|
||||
// // Let the system compositor draw all shadows for us.
|
||||
// set_needs_system_composite(true);
|
||||
//#else
|
||||
// We will draw the shadow in Paint(), so add some margin to the paint
|
||||
// bounds to leave space for the shadow. We fill this whole region and clip
|
||||
// children to it so we don't need to join the child paint bounds.
|
||||
set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation_,
|
||||
device_pixel_ratio_));
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation(),
|
||||
context->frame_device_pixel_ratio));
|
||||
//#endif // defined(OS_FUCHSIA)
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,8 +94,8 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
|
||||
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
|
||||
// If we can't find an existing retained surface, create one.
|
||||
SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_,
|
||||
total_elevation_, viewport_depth_, this);
|
||||
SceneUpdateContext::Frame frame(context, frameRRect_, color(), elevation(),
|
||||
this);
|
||||
for (auto& layer : layers()) {
|
||||
if (layer->needs_painting()) {
|
||||
frame.AddPaintLayer(layer.get());
|
||||
@ -116,14 +111,14 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
if (elevation_ != 0) {
|
||||
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_,
|
||||
SkColorGetA(color_) != 0xff, device_pixel_ratio_);
|
||||
if (elevation() != 0) {
|
||||
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation(),
|
||||
SkColorGetA(color()) != 0xff, context.frame_device_pixel_ratio);
|
||||
}
|
||||
|
||||
// Call drawPath without clip if possible for better performance.
|
||||
SkPaint paint;
|
||||
paint.setColor(color_);
|
||||
paint.setColor(color());
|
||||
paint.setAntiAlias(true);
|
||||
if (clip_behavior_ != Clip::antiAliasWithSaveLayer) {
|
||||
context.leaf_nodes_canvas->drawPath(path_, paint);
|
||||
|
||||
@ -5,20 +5,33 @@
|
||||
#ifndef FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include "flutter/flow/layers/fuchsia_system_composited_layer.h"
|
||||
#endif
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class PhysicalShapeLayer : public ContainerLayer {
|
||||
#if !defined(OS_FUCHSIA)
|
||||
class PhysicalShapeLayerBase : public ElevatedContainerLayer {
|
||||
public:
|
||||
PhysicalShapeLayer(SkColor color,
|
||||
SkColor shadow_color,
|
||||
SkScalar device_pixel_ratio,
|
||||
float viewport_depth,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior);
|
||||
static bool can_system_composite() { return false; }
|
||||
|
||||
PhysicalShapeLayerBase(SkColor color, float elevation)
|
||||
: ElevatedContainerLayer(elevation), color_(color) {}
|
||||
|
||||
void set_dimensions(SkRRect rrect) {}
|
||||
SkColor color() const { return color_; }
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
};
|
||||
#else
|
||||
using PhysicalShapeLayerBase = FuchsiaSystemCompositedLayer;
|
||||
#endif
|
||||
|
||||
class PhysicalShapeLayer : public PhysicalShapeLayerBase {
|
||||
public:
|
||||
static SkRect ComputeShadowBounds(const SkRect& bounds,
|
||||
float elevation,
|
||||
float pixel_ratio);
|
||||
@ -29,8 +42,13 @@ class PhysicalShapeLayer : public ContainerLayer {
|
||||
bool transparentOccluder,
|
||||
SkScalar dpr);
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
PhysicalShapeLayer(SkColor color,
|
||||
SkColor shadow_color,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior);
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext& context) const override;
|
||||
|
||||
bool UsesSaveLayer() const {
|
||||
@ -41,17 +59,8 @@ class PhysicalShapeLayer : public ContainerLayer {
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
float total_elevation() const { return total_elevation_; }
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
SkColor shadow_color_;
|
||||
SkScalar device_pixel_ratio_;
|
||||
#if defined(OS_FUCHSIA)
|
||||
float viewport_depth_ = 0.0f;
|
||||
#endif
|
||||
float elevation_ = 0.0f;
|
||||
float total_elevation_ = 0.0f;
|
||||
SkPath path_;
|
||||
bool isRect_;
|
||||
SkRRect frameRRect_;
|
||||
|
||||
@ -18,8 +18,6 @@ using PhysicalShapeLayerTest = LayerTest;
|
||||
TEST_F(PhysicalShapeLayerTest, PaintingEmptyLayerDies) {
|
||||
auto layer =
|
||||
std::make_shared<PhysicalShapeLayer>(SK_ColorBLACK, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
0.0f, // elevation
|
||||
SkPath(), Clip::none);
|
||||
|
||||
@ -38,8 +36,6 @@ TEST_F(PhysicalShapeLayerTest, PaintBeforePreollDies) {
|
||||
auto mock_layer = std::make_shared<MockLayer>(child_path, SkPaint());
|
||||
auto layer =
|
||||
std::make_shared<PhysicalShapeLayer>(SK_ColorBLACK, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
0.0f, // elevation
|
||||
SkPath(), Clip::none);
|
||||
layer->Add(mock_layer);
|
||||
@ -54,8 +50,6 @@ TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) {
|
||||
layer_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
auto layer =
|
||||
std::make_shared<PhysicalShapeLayer>(SK_ColorGREEN, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
0.0f, // elevation
|
||||
layer_path, Clip::none);
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
@ -80,20 +74,14 @@ TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPath) {
|
||||
SkPath child2_path;
|
||||
child2_path.addRect(3, 2, 5, 15).close();
|
||||
auto child1 = std::make_shared<PhysicalShapeLayer>(SK_ColorRED, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
0.0f, // elevation
|
||||
child1_path, Clip::none);
|
||||
auto child2 =
|
||||
std::make_shared<PhysicalShapeLayer>(SK_ColorBLUE, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
0.0f, // elevation
|
||||
child2_path, Clip::none);
|
||||
auto layer =
|
||||
std::make_shared<PhysicalShapeLayer>(SK_ColorGREEN, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
0.0f, // elevation
|
||||
layer_path, Clip::none);
|
||||
layer->Add(child1);
|
||||
@ -133,10 +121,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
|
||||
SkPath layer_path;
|
||||
layer_path.addRect(0, 0, 8, 8).close();
|
||||
auto layer = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorGREEN, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
initial_elevation, layer_path, Clip::none);
|
||||
SK_ColorGREEN, SK_ColorBLACK, initial_elevation, layer_path, Clip::none);
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
|
||||
@ -190,10 +175,8 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
|
||||
std::shared_ptr<PhysicalShapeLayer> layers[4];
|
||||
for (int i = 0; i < 4; i += 1) {
|
||||
layers[i] = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorBLACK, SK_ColorBLACK,
|
||||
1.0f, // pixel ratio
|
||||
1.0f, // depth
|
||||
initial_elevations[i], layer_path, Clip::none);
|
||||
SK_ColorBLACK, SK_ColorBLACK, initial_elevations[i], layer_path,
|
||||
Clip::none);
|
||||
}
|
||||
layers[0]->Add(layers[1]);
|
||||
layers[0]->Add(layers[2]);
|
||||
@ -251,10 +234,10 @@ static bool ReadbackResult(PrerollContext* context,
|
||||
const SkMatrix initial_matrix = SkMatrix();
|
||||
const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
|
||||
const SkPath layer_path = SkPath().addRect(layer_bounds);
|
||||
auto layer = std::make_shared<PhysicalShapeLayer>(SK_ColorGREEN,
|
||||
SK_ColorBLACK, 1.0f, 1.0f,
|
||||
0.0f, // elevation
|
||||
layer_path, clip_behavior);
|
||||
auto layer =
|
||||
std::make_shared<PhysicalShapeLayer>(SK_ColorGREEN, SK_ColorBLACK,
|
||||
0.0f, // elevation
|
||||
layer_path, clip_behavior);
|
||||
if (child != nullptr) {
|
||||
layer->Add(child);
|
||||
}
|
||||
|
||||
@ -175,7 +175,9 @@ void RasterCache::Prepare(PrerollContext* context,
|
||||
context->ui_time,
|
||||
context->texture_registry,
|
||||
context->has_platform_view ? nullptr : context->raster_cache,
|
||||
context->checkerboard_offscreen_layers};
|
||||
context->checkerboard_offscreen_layers,
|
||||
context->frame_physical_depth,
|
||||
context->frame_device_pixel_ratio};
|
||||
if (layer->needs_painting()) {
|
||||
layer->Paint(paintContext);
|
||||
}
|
||||
|
||||
@ -212,7 +212,9 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
|
||||
frame.context().ui_time(),
|
||||
frame.context().texture_registry(),
|
||||
&frame.context().raster_cache(),
|
||||
false};
|
||||
false,
|
||||
frame_physical_depth_,
|
||||
frame_device_pixel_ratio_};
|
||||
canvas->restoreToCount(1);
|
||||
canvas->save();
|
||||
canvas->clear(task.background_color);
|
||||
@ -299,29 +301,14 @@ SceneUpdateContext::Shape::Shape(SceneUpdateContext& context)
|
||||
SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float local_elevation,
|
||||
float world_elevation,
|
||||
float depth,
|
||||
float elevation,
|
||||
Layer* layer)
|
||||
: Shape(context),
|
||||
rrect_(rrect),
|
||||
color_(color),
|
||||
paint_bounds_(SkRect::MakeEmpty()),
|
||||
layer_(layer) {
|
||||
if (depth > -1 && world_elevation > depth) {
|
||||
// TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be
|
||||
// able to have developers specify the behavior here to alternatives besides
|
||||
// clamping, like normalization on some arbitrary curve.
|
||||
|
||||
// Clamp the local z coordinate at our max bound. Take into account the
|
||||
// parent z position here to fix clamping in cases where the child is
|
||||
// overflowing because of its parents.
|
||||
const float parent_elevation = world_elevation - local_elevation;
|
||||
local_elevation = depth - parent_elevation;
|
||||
}
|
||||
if (local_elevation != 0.0) {
|
||||
entity_node().SetTranslation(0.f, 0.f, -local_elevation);
|
||||
}
|
||||
entity_node().SetTranslation(0.f, 0.f, -elevation);
|
||||
}
|
||||
|
||||
SceneUpdateContext::Frame::~Frame() {
|
||||
|
||||
@ -115,9 +115,7 @@ class SceneUpdateContext {
|
||||
Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float local_elevation = 0.0f,
|
||||
float parent_elevation = 0.0f,
|
||||
float depth = 0.0f,
|
||||
float elevation = 0.0f,
|
||||
Layer* layer = nullptr);
|
||||
virtual ~Frame();
|
||||
|
||||
@ -152,6 +150,17 @@ class SceneUpdateContext {
|
||||
}
|
||||
const fuchsia::ui::gfx::MetricsPtr& metrics() const { return metrics_; }
|
||||
|
||||
void set_dimensions(const SkISize& frame_physical_size,
|
||||
float frame_physical_depth,
|
||||
float frame_device_pixel_ratio) {
|
||||
frame_physical_size_ = frame_physical_size;
|
||||
frame_physical_depth_ = frame_physical_depth;
|
||||
frame_device_pixel_ratio_ = frame_device_pixel_ratio;
|
||||
}
|
||||
const SkISize& frame_size() const { return frame_physical_size_; }
|
||||
float frame_physical_depth() const { return frame_physical_depth_; }
|
||||
float frame_device_pixel_ratio() const { return frame_device_pixel_ratio_; }
|
||||
|
||||
// TODO(chinmaygarde): This method must submit the surfaces as soon as paint
|
||||
// tasks are done. However, given that there is no support currently for
|
||||
// Vulkan semaphores, we need to submit all the surfaces after an explicit
|
||||
@ -225,6 +234,10 @@ class SceneUpdateContext {
|
||||
SurfaceProducer* const surface_producer_;
|
||||
|
||||
fuchsia::ui::gfx::MetricsPtr metrics_;
|
||||
SkISize frame_physical_size_;
|
||||
float frame_physical_depth_ = 0.0f;
|
||||
float frame_device_pixel_ratio_ =
|
||||
1.0f; // Ratio between logical and physical pixels.
|
||||
|
||||
std::vector<PaintTask> paint_tasks_;
|
||||
|
||||
|
||||
@ -39,8 +39,11 @@ class LayerTestBase : public CanvasTestBase<BaseT> {
|
||||
kGiantRect, /* cull_rect */
|
||||
false, /* layer reads from surface */
|
||||
raster_time_, ui_time_, texture_registry_,
|
||||
false, /* checkerboard_offscreen_layers */
|
||||
0.0f /* total_elevation */
|
||||
false, /* checkerboard_offscreen_layers */
|
||||
100.0f, /* frame_physical_depth */
|
||||
1.0f, /* frame_device_pixel_ratio */
|
||||
0.0f, /* total_elevation */
|
||||
false, /* has_platform_view */
|
||||
}),
|
||||
paint_context_({
|
||||
TestT::mock_canvas().internal_canvas(), /* internal_nodes_canvas */
|
||||
@ -50,6 +53,8 @@ class LayerTestBase : public CanvasTestBase<BaseT> {
|
||||
raster_time_, ui_time_, texture_registry_,
|
||||
nullptr, /* raster_cache */
|
||||
false, /* checkerboard_offscreen_layers */
|
||||
100.0f, /* frame_physical_depth */
|
||||
1.0f, /* frame_device_pixel_ratio */
|
||||
}) {}
|
||||
|
||||
TextureRegistry& texture_regitry() { return texture_registry_; }
|
||||
|
||||
@ -104,14 +104,11 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context,
|
||||
const SkSize& size,
|
||||
bool hit_testable) {
|
||||
if (pending_view_holder_token_.value) {
|
||||
opacity_node_ =
|
||||
std::make_unique<scenic::OpacityNodeHACK>(context.session());
|
||||
entity_node_ = std::make_unique<scenic::EntityNode>(context.session());
|
||||
view_holder_ = std::make_unique<scenic::ViewHolder>(
|
||||
context.session(), std::move(pending_view_holder_token_),
|
||||
"Flutter SceneHost");
|
||||
|
||||
opacity_node_->AddChild(*entity_node_);
|
||||
entity_node_->Attach(*view_holder_);
|
||||
ui_task_runner_->PostTask(
|
||||
[bind_callback = std::move(pending_bind_callback_),
|
||||
@ -119,20 +116,18 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context,
|
||||
bind_callback(view_holder_id);
|
||||
});
|
||||
}
|
||||
FML_DCHECK(opacity_node_);
|
||||
FML_DCHECK(entity_node_);
|
||||
FML_DCHECK(view_holder_);
|
||||
|
||||
context.top_entity()->entity_node().AddChild(*opacity_node_);
|
||||
context.top_entity()->embedder_node().AddChild(*entity_node_);
|
||||
entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f);
|
||||
entity_node_->SetHitTestBehavior(
|
||||
hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault
|
||||
: fuchsia::ui::gfx::HitTestBehavior::kSuppress);
|
||||
if (has_pending_opacity_) {
|
||||
opacity_node_->SetOpacity(pending_opacity_);
|
||||
|
||||
has_pending_opacity_ = false;
|
||||
}
|
||||
if (has_pending_properties_) {
|
||||
// TODO(dworsham): This should be derived from size and elevation. We
|
||||
// should be able to Z-limit the view's box but otherwise it uses all of the
|
||||
// available airspace.
|
||||
view_holder_->SetViewProperties(std::move(pending_properties_));
|
||||
|
||||
has_pending_properties_ = false;
|
||||
@ -151,9 +146,4 @@ void ViewHolder::SetProperties(double width,
|
||||
has_pending_properties_ = true;
|
||||
}
|
||||
|
||||
void ViewHolder::SetOpacity(double opacity) {
|
||||
pending_opacity_ = std::clamp(opacity, 0.0, 1.0);
|
||||
has_pending_opacity_ = true;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -51,7 +51,6 @@ class ViewHolder {
|
||||
double insetBottom,
|
||||
double insetLeft,
|
||||
bool focusable);
|
||||
void SetOpacity(double opacity);
|
||||
|
||||
// Creates or updates the contained ViewHolder resource using the specified
|
||||
// |SceneUpdateContext|.
|
||||
@ -63,7 +62,6 @@ class ViewHolder {
|
||||
private:
|
||||
fml::RefPtr<fml::TaskRunner> ui_task_runner_;
|
||||
|
||||
std::unique_ptr<scenic::OpacityNodeHACK> opacity_node_;
|
||||
std::unique_ptr<scenic::EntityNode> entity_node_;
|
||||
std::unique_ptr<scenic::ViewHolder> view_holder_;
|
||||
|
||||
@ -71,9 +69,7 @@ class ViewHolder {
|
||||
BindCallback pending_bind_callback_;
|
||||
|
||||
fuchsia::ui::gfx::ViewProperties pending_properties_;
|
||||
double pending_opacity_;
|
||||
bool has_pending_properties_ = false;
|
||||
bool has_pending_opacity_ = false;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ViewHolder);
|
||||
};
|
||||
|
||||
@ -694,13 +694,6 @@ class SceneHost extends NativeFieldWrapperClass2 {
|
||||
void Function(bool) viewStateChangedCallback) {
|
||||
_constructor(viewHolderToken, viewConnectedCallback, viewDisconnectedCallback, viewStateChangedCallback);
|
||||
}
|
||||
SceneHost.fromViewHolderToken(
|
||||
dynamic viewHolderToken,
|
||||
void Function() viewConnectedCallback,
|
||||
void Function() viewDisconnectedCallback,
|
||||
void Function(bool) viewStateChangedCallback) {
|
||||
_constructor(viewHolderToken, viewConnectedCallback, viewDisconnectedCallback, viewStateChangedCallback);
|
||||
}
|
||||
|
||||
void _constructor(dynamic viewHolderToken, void Function() viewConnectedCallback, void Function() viewDisconnectedCallback, void Function(bool) viewStateChangedCallback)
|
||||
native 'SceneHost_constructor';
|
||||
@ -720,8 +713,4 @@ class SceneHost extends NativeFieldWrapperClass2 {
|
||||
double insetBottom,
|
||||
double insetLeft,
|
||||
bool focusable) native 'SceneHost_setProperties';
|
||||
|
||||
/// Set the opacity of the linked scene. This opacity value is applied only
|
||||
/// once, when the child scene is composited into our own.
|
||||
void setOpacity(double opacity) native 'SceneHost_setOpacity';
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "flutter/lib/ui/painting/image.h"
|
||||
#include "flutter/lib/ui/painting/picture.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/skia/include/core/SkImageInfo.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
@ -36,13 +38,19 @@ fml::RefPtr<Scene> Scene::create(std::shared_ptr<flutter::Layer> rootLayer,
|
||||
Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
|
||||
uint32_t rasterizerTracingThreshold,
|
||||
bool checkerboardRasterCacheImages,
|
||||
bool checkerboardOffscreenLayers)
|
||||
: m_layerTree(new flutter::LayerTree()) {
|
||||
m_layerTree->set_root_layer(std::move(rootLayer));
|
||||
m_layerTree->set_rasterizer_tracing_threshold(rasterizerTracingThreshold);
|
||||
m_layerTree->set_checkerboard_raster_cache_images(
|
||||
bool checkerboardOffscreenLayers) {
|
||||
auto viewport_metrics = UIDartState::Current()->window()->viewport_metrics();
|
||||
|
||||
layer_tree_ = std::make_unique<LayerTree>(
|
||||
SkISize::Make(viewport_metrics.physical_width,
|
||||
viewport_metrics.physical_height),
|
||||
static_cast<float>(viewport_metrics.physical_depth),
|
||||
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);
|
||||
m_layerTree->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers);
|
||||
layer_tree_->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers);
|
||||
}
|
||||
|
||||
Scene::~Scene() {}
|
||||
@ -56,11 +64,11 @@ Dart_Handle Scene::toImage(uint32_t width,
|
||||
Dart_Handle raw_image_callback) {
|
||||
TRACE_EVENT0("flutter", "Scene::toImage");
|
||||
|
||||
if (!m_layerTree) {
|
||||
if (!layer_tree_) {
|
||||
return tonic::ToDart("Scene did not contain a layer tree.");
|
||||
}
|
||||
|
||||
auto picture = m_layerTree->Flatten(SkRect::MakeWH(width, height));
|
||||
auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height));
|
||||
if (!picture) {
|
||||
return tonic::ToDart("Could not flatten scene into a layer tree.");
|
||||
}
|
||||
@ -69,7 +77,7 @@ Dart_Handle Scene::toImage(uint32_t width,
|
||||
}
|
||||
|
||||
std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() {
|
||||
return std::move(m_layerTree);
|
||||
return std::move(layer_tree_);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -45,7 +45,7 @@ class Scene : public RefCountedDartWrappable<Scene> {
|
||||
bool checkerboardRasterCacheImages,
|
||||
bool checkerboardOffscreenLayers);
|
||||
|
||||
std::unique_ptr<flutter::LayerTree> m_layerTree;
|
||||
std::unique_ptr<flutter::LayerTree> layer_tree_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -23,8 +23,6 @@
|
||||
#include "flutter/fml/build_config.h"
|
||||
#include "flutter/lib/ui/painting/matrix.h"
|
||||
#include "flutter/lib/ui/painting/shader.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/skia/include/core/SkColorFilter.h"
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/dart_args.h"
|
||||
@ -181,12 +179,6 @@ fml::RefPtr<EngineLayer> SceneBuilder::pushPhysicalShape(const CanvasPath* path,
|
||||
int clipBehavior) {
|
||||
auto layer = std::make_shared<flutter::PhysicalShapeLayer>(
|
||||
static_cast<SkColor>(color), static_cast<SkColor>(shadow_color),
|
||||
static_cast<float>(UIDartState::Current()
|
||||
->window()
|
||||
->viewport_metrics()
|
||||
.device_pixel_ratio),
|
||||
static_cast<float>(
|
||||
UIDartState::Current()->window()->viewport_metrics().physical_depth),
|
||||
static_cast<float>(elevation), path->path(),
|
||||
static_cast<flutter::Clip>(clipBehavior));
|
||||
PushLayer(layer);
|
||||
@ -194,33 +186,24 @@ fml::RefPtr<EngineLayer> SceneBuilder::pushPhysicalShape(const CanvasPath* path,
|
||||
}
|
||||
|
||||
void SceneBuilder::addRetained(fml::RefPtr<EngineLayer> retainedLayer) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
current_layer_->Add(retainedLayer->Layer());
|
||||
AddLayer(retainedLayer->Layer());
|
||||
}
|
||||
|
||||
void SceneBuilder::pop() {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
current_layer_ = current_layer_->parent();
|
||||
PopLayer();
|
||||
}
|
||||
|
||||
void SceneBuilder::addPicture(double dx,
|
||||
double dy,
|
||||
Picture* picture,
|
||||
int hints) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
SkPoint offset = SkPoint::Make(dx, dy);
|
||||
SkRect pictureRect = picture->picture()->cullRect();
|
||||
pictureRect.offset(offset.x(), offset.y());
|
||||
auto layer = std::make_unique<flutter::PictureLayer>(
|
||||
offset, UIDartState::CreateGPUObject(picture->picture()), !!(hints & 1),
|
||||
!!(hints & 2));
|
||||
current_layer_->Add(std::move(layer));
|
||||
AddLayer(std::move(layer));
|
||||
}
|
||||
|
||||
void SceneBuilder::addTexture(double dx,
|
||||
@ -229,12 +212,9 @@ void SceneBuilder::addTexture(double dx,
|
||||
double height,
|
||||
int64_t textureId,
|
||||
bool freeze) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
auto layer = std::make_unique<flutter::TextureLayer>(
|
||||
SkPoint::Make(dx, dy), SkSize::Make(width, height), textureId, freeze);
|
||||
current_layer_->Add(std::move(layer));
|
||||
AddLayer(std::move(layer));
|
||||
}
|
||||
|
||||
void SceneBuilder::addPlatformView(double dx,
|
||||
@ -242,12 +222,9 @@ void SceneBuilder::addPlatformView(double dx,
|
||||
double width,
|
||||
double height,
|
||||
int64_t viewId) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
auto layer = std::make_unique<flutter::PlatformViewLayer>(
|
||||
SkPoint::Make(dx, dy), SkSize::Make(width, height), viewId);
|
||||
current_layer_->Add(std::move(layer));
|
||||
AddLayer(std::move(layer));
|
||||
}
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
@ -257,13 +234,10 @@ void SceneBuilder::addChildScene(double dx,
|
||||
double height,
|
||||
SceneHost* sceneHost,
|
||||
bool hitTestable) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
auto layer = std::make_unique<flutter::ChildSceneLayer>(
|
||||
sceneHost->id(), SkPoint::Make(dx, dy), SkSize::Make(width, height),
|
||||
hitTestable);
|
||||
current_layer_->Add(std::move(layer));
|
||||
AddLayer(std::move(layer));
|
||||
}
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
@ -272,14 +246,11 @@ void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions,
|
||||
double right,
|
||||
double top,
|
||||
double bottom) {
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
}
|
||||
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
auto layer =
|
||||
std::make_unique<flutter::PerformanceOverlayLayer>(enabledOptions);
|
||||
layer->set_paint_bounds(rect);
|
||||
current_layer_->Add(std::move(layer));
|
||||
AddLayer(std::move(layer));
|
||||
}
|
||||
|
||||
void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) {
|
||||
@ -295,29 +266,33 @@ void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
|
||||
}
|
||||
|
||||
fml::RefPtr<Scene> SceneBuilder::build() {
|
||||
FML_DCHECK(layer_stack_.size() >= 1);
|
||||
|
||||
fml::RefPtr<Scene> scene = Scene::create(
|
||||
std::move(root_layer_), rasterizer_tracing_threshold_,
|
||||
layer_stack_[0], rasterizer_tracing_threshold_,
|
||||
checkerboard_raster_cache_images_, checkerboard_offscreen_layers_);
|
||||
ClearDartWrapper();
|
||||
ClearDartWrapper(); // may delete this object.
|
||||
return scene;
|
||||
}
|
||||
|
||||
void SceneBuilder::PushLayer(std::shared_ptr<flutter::ContainerLayer> layer) {
|
||||
void SceneBuilder::AddLayer(std::shared_ptr<Layer> layer) {
|
||||
FML_DCHECK(layer);
|
||||
|
||||
if (!root_layer_) {
|
||||
root_layer_ = std::move(layer);
|
||||
current_layer_ = root_layer_.get();
|
||||
return;
|
||||
if (!layer_stack_.empty()) {
|
||||
layer_stack_.back()->Add(std::move(layer));
|
||||
}
|
||||
}
|
||||
|
||||
if (!current_layer_) {
|
||||
return;
|
||||
void SceneBuilder::PushLayer(std::shared_ptr<ContainerLayer> layer) {
|
||||
AddLayer(layer);
|
||||
layer_stack_.push_back(std::move(layer));
|
||||
}
|
||||
|
||||
void SceneBuilder::PopLayer() {
|
||||
// We never pop the root layer, so that AddLayer operations are always valid.
|
||||
if (layer_stack_.size() > 1) {
|
||||
layer_stack_.pop_back();
|
||||
}
|
||||
|
||||
flutter::ContainerLayer* newLayer = layer.get();
|
||||
current_layer_->Add(std::move(layer));
|
||||
current_layer_ = newLayer;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -8,8 +8,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
#include "flutter/lib/ui/compositing/scene.h"
|
||||
#include "flutter/lib/ui/dart_wrapper.h"
|
||||
#include "flutter/lib/ui/painting/color_filter.h"
|
||||
@ -35,7 +36,6 @@ class SceneBuilder : public RefCountedDartWrappable<SceneBuilder> {
|
||||
static fml::RefPtr<SceneBuilder> create() {
|
||||
return fml::MakeRefCounted<SceneBuilder>();
|
||||
}
|
||||
|
||||
~SceneBuilder() override;
|
||||
|
||||
fml::RefPtr<EngineLayer> pushTransform(tonic::Float64List& matrix4);
|
||||
@ -98,7 +98,6 @@ class SceneBuilder : public RefCountedDartWrappable<SceneBuilder> {
|
||||
#endif
|
||||
|
||||
void setRasterizerTracingThreshold(uint32_t frameInterval);
|
||||
|
||||
void setCheckerboardRasterCacheImages(bool checkerboard);
|
||||
void setCheckerboardOffscreenLayers(bool checkerboard);
|
||||
|
||||
@ -109,15 +108,15 @@ class SceneBuilder : public RefCountedDartWrappable<SceneBuilder> {
|
||||
private:
|
||||
SceneBuilder();
|
||||
|
||||
std::shared_ptr<flutter::ContainerLayer> root_layer_;
|
||||
flutter::ContainerLayer* current_layer_ = nullptr;
|
||||
void AddLayer(std::shared_ptr<Layer> layer);
|
||||
void PushLayer(std::shared_ptr<ContainerLayer> layer);
|
||||
void PopLayer();
|
||||
|
||||
std::vector<std::shared_ptr<ContainerLayer>> layer_stack_;
|
||||
int rasterizer_tracing_threshold_ = 0;
|
||||
bool checkerboard_raster_cache_images_ = false;
|
||||
bool checkerboard_offscreen_layers_ = false;
|
||||
|
||||
void PushLayer(std::shared_ptr<flutter::ContainerLayer> layer);
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(SceneBuilder);
|
||||
};
|
||||
|
||||
|
||||
@ -85,10 +85,9 @@ namespace flutter {
|
||||
|
||||
IMPLEMENT_WRAPPERTYPEINFO(ui, SceneHost);
|
||||
|
||||
#define FOR_EACH_BINDING(V) \
|
||||
V(SceneHost, dispose) \
|
||||
V(SceneHost, setProperties) \
|
||||
V(SceneHost, setOpacity)
|
||||
#define FOR_EACH_BINDING(V) \
|
||||
V(SceneHost, dispose) \
|
||||
V(SceneHost, setProperties)
|
||||
|
||||
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
|
||||
|
||||
@ -205,13 +204,4 @@ void SceneHost::setProperties(double width,
|
||||
});
|
||||
}
|
||||
|
||||
void SceneHost::setOpacity(double opacity) {
|
||||
gpu_task_runner_->PostTask([id = koid_, opacity]() {
|
||||
auto* view_holder = flutter::ViewHolder::FromId(id);
|
||||
FML_DCHECK(view_holder);
|
||||
|
||||
view_holder->SetOpacity(opacity);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -33,14 +33,11 @@ class SceneHost : public RefCountedDartWrappable<SceneHost> {
|
||||
static void OnViewDisconnected(scenic::ResourceId id);
|
||||
static void OnViewStateChanged(scenic::ResourceId id, bool state);
|
||||
|
||||
SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
|
||||
Dart_Handle viewConnectedCallback,
|
||||
Dart_Handle viewDisconnectedCallback,
|
||||
Dart_Handle viewStateChangedCallback);
|
||||
~SceneHost() override;
|
||||
|
||||
zx_koid_t id() const { return koid_; }
|
||||
|
||||
// These are visible to Dart.
|
||||
void dispose();
|
||||
void setProperties(double width,
|
||||
double height,
|
||||
@ -49,9 +46,13 @@ class SceneHost : public RefCountedDartWrappable<SceneHost> {
|
||||
double insetBottom,
|
||||
double insetLeft,
|
||||
bool focusable);
|
||||
void setOpacity(double opacity);
|
||||
|
||||
private:
|
||||
SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
|
||||
Dart_Handle viewConnectedCallback,
|
||||
Dart_Handle viewDisconnectedCallback,
|
||||
Dart_Handle viewStateChangedCallback);
|
||||
|
||||
fml::RefPtr<fml::TaskRunner> gpu_task_runner_;
|
||||
tonic::DartPersistentValue view_connected_callback_;
|
||||
tonic::DartPersistentValue view_disconnected_callback_;
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
|
||||
#include "flutter/lib/ui/painting/engine_layer.h"
|
||||
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/dart_args.h"
|
||||
#include "third_party/tonic/dart_binding_macros.h"
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "flutter/lib/ui/dart_wrapper.h"
|
||||
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
|
||||
namespace tonic {
|
||||
class DartLibraryNatives;
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
|
||||
#include "flutter/lib/ui/window/viewport_metrics.h"
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
|
||||
namespace flutter {
|
||||
ViewportMetrics::ViewportMetrics() = default;
|
||||
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
@ -39,6 +40,10 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
physical_system_gesture_inset_bottom(
|
||||
p_physical_system_gesture_inset_bottom),
|
||||
physical_system_gesture_inset_left(p_physical_system_gesture_inset_left) {
|
||||
// Ensure we don't have nonsensical dimensions.
|
||||
FML_DCHECK(physical_width >= 0);
|
||||
FML_DCHECK(physical_height >= 0);
|
||||
FML_DCHECK(device_pixel_ratio > 0);
|
||||
}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
@ -68,8 +73,11 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
physical_view_inset_bottom(p_physical_view_inset_bottom),
|
||||
physical_view_inset_left(p_physical_view_inset_left),
|
||||
physical_view_inset_front(p_physical_view_inset_front),
|
||||
physical_view_inset_back(p_physical_view_inset_back) {}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(const ViewportMetrics& other) = default;
|
||||
physical_view_inset_back(p_physical_view_inset_back) {
|
||||
// Ensure we don't have nonsensical dimensions.
|
||||
FML_DCHECK(physical_width >= 0);
|
||||
FML_DCHECK(physical_height >= 0);
|
||||
FML_DCHECK(device_pixel_ratio > 0);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -16,7 +16,8 @@ namespace flutter {
|
||||
static const double kUnsetDepth = 1.7976931348623157e+308;
|
||||
|
||||
struct ViewportMetrics {
|
||||
ViewportMetrics();
|
||||
ViewportMetrics() = default;
|
||||
ViewportMetrics(const ViewportMetrics& other) = default;
|
||||
|
||||
// Create a 2D ViewportMetrics instance.
|
||||
ViewportMetrics(double p_device_pixel_ratio,
|
||||
@ -51,8 +52,6 @@ struct ViewportMetrics {
|
||||
double p_physical_view_inset_bottom,
|
||||
double p_physical_view_inset_left);
|
||||
|
||||
ViewportMetrics(const ViewportMetrics& other);
|
||||
|
||||
double device_pixel_ratio = 1.0;
|
||||
double physical_width = 0;
|
||||
double physical_height = 0;
|
||||
|
||||
@ -383,12 +383,6 @@ class SceneHost {
|
||||
void Function() viewDisconnectedCallback,
|
||||
void Function(bool) viewStateChangedCallback);
|
||||
|
||||
SceneHost.fromViewHolderToken(
|
||||
dynamic viewHolderToken,
|
||||
void Function() viewConnectedCallback,
|
||||
void Function() viewDisconnectedCallback,
|
||||
void Function(bool) viewStateChangedCallback);
|
||||
|
||||
/// Releases the resources associated with the SceneHost.
|
||||
///
|
||||
/// After calling this function, the SceneHost cannot be used further.
|
||||
@ -400,10 +394,4 @@ class SceneHost {
|
||||
double insetRight, double insetBottom, double insetLeft, bool focusable) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
/// Set the opacity of the linked scene. This opacity value is applied only
|
||||
/// once, when the child scene is composited into our own.
|
||||
void setOpacity(double opacity) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,13 +437,12 @@ void Engine::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
|
||||
if (!layer_tree)
|
||||
return;
|
||||
|
||||
SkISize frame_size = SkISize::Make(viewport_metrics_.physical_width,
|
||||
viewport_metrics_.physical_height);
|
||||
if (frame_size.isEmpty())
|
||||
// Ensure frame dimensions are sane.
|
||||
if (layer_tree->frame_size().isEmpty() ||
|
||||
layer_tree->frame_physical_depth() <= 0.0f ||
|
||||
layer_tree->frame_device_pixel_ratio() <= 0.0f)
|
||||
return;
|
||||
|
||||
layer_tree->set_frame_size(frame_size);
|
||||
layer_tree->set_device_pixel_ratio(viewport_metrics_.device_pixel_ratio);
|
||||
animator_->Render(std::move(layer_tree));
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ TEST_F(ShellTest, CacheSkSLWorks) {
|
||||
SkPath path;
|
||||
path.addCircle(50, 50, 20);
|
||||
auto physical_shape_layer = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorRED, SK_ColorBLUE, 1.0f, 1.0f, 1.0f, path, Clip::antiAlias);
|
||||
SK_ColorRED, SK_ColorBLUE, 1.0f, path, Clip::antiAlias);
|
||||
root->Add(physical_shape_layer);
|
||||
};
|
||||
PumpOneFrame(shell.get(), 100, 100, builder);
|
||||
|
||||
@ -143,14 +143,22 @@ void ShellTest::PumpOneFrame(Shell* shell,
|
||||
double width,
|
||||
double height,
|
||||
LayerTreeBuilder builder) {
|
||||
PumpOneFrame(shell,
|
||||
flutter::ViewportMetrics{1, width, height, flutter::kUnsetDepth,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
std::move(builder));
|
||||
}
|
||||
|
||||
void ShellTest::PumpOneFrame(Shell* shell,
|
||||
flutter::ViewportMetrics viewport_metrics,
|
||||
LayerTreeBuilder builder) {
|
||||
// Set viewport to nonempty, and call Animator::BeginFrame to make the layer
|
||||
// tree pipeline nonempty. Without either of this, the layer tree below
|
||||
// won't be rasterized.
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
shell->GetTaskRunners().GetUITaskRunner()->PostTask(
|
||||
[&latch, engine = shell->weak_engine_, width, height]() {
|
||||
engine->SetViewportMetrics(
|
||||
{1, width, height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
[&latch, engine = shell->weak_engine_, viewport_metrics]() {
|
||||
engine->SetViewportMetrics(std::move(viewport_metrics));
|
||||
const auto frame_begin_time = fml::TimePoint::Now();
|
||||
const auto frame_end_time =
|
||||
frame_begin_time + fml::TimeDelta::FromSecondsF(1.0 / 60.0);
|
||||
@ -163,8 +171,12 @@ void ShellTest::PumpOneFrame(Shell* shell,
|
||||
// Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized|
|
||||
fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_;
|
||||
shell->GetTaskRunners().GetUITaskRunner()->PostTask(
|
||||
[&latch, runtime_delegate, &builder]() {
|
||||
auto layer_tree = std::make_unique<LayerTree>();
|
||||
[&latch, runtime_delegate, &builder, viewport_metrics]() {
|
||||
auto layer_tree = std::make_unique<LayerTree>(
|
||||
SkISize::Make(viewport_metrics.physical_width,
|
||||
viewport_metrics.physical_height),
|
||||
static_cast<float>(viewport_metrics.physical_depth),
|
||||
static_cast<float>(viewport_metrics.device_pixel_ratio));
|
||||
SkMatrix identity;
|
||||
identity.setIdentity();
|
||||
auto root_layer = std::make_shared<TransformLayer>(identity);
|
||||
|
||||
@ -59,7 +59,9 @@ class ShellTest : public ThreadTest {
|
||||
double width = 1,
|
||||
double height = 1,
|
||||
LayerTreeBuilder = {});
|
||||
|
||||
static void PumpOneFrame(Shell* shell,
|
||||
flutter::ViewportMetrics viewport_metrics,
|
||||
LayerTreeBuilder = {});
|
||||
static void DispatchFakePointerData(Shell* shell);
|
||||
static void DispatchPointerData(Shell* shell,
|
||||
std::unique_ptr<PointerDataPacket> packet);
|
||||
|
||||
@ -611,6 +611,27 @@ TEST_F(ShellTest, WaitForFirstFrame) {
|
||||
fml::Status result =
|
||||
shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000));
|
||||
ASSERT_TRUE(result.ok());
|
||||
|
||||
DestroyShell(std::move(shell));
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, WaitForFirstFrameZeroSizeFrame) {
|
||||
auto settings = CreateSettingsForFixture();
|
||||
std::unique_ptr<Shell> shell = CreateShell(settings);
|
||||
|
||||
// Create the surface needed by rasterizer
|
||||
PlatformViewNotifyCreated(shell.get());
|
||||
|
||||
auto configuration = RunConfiguration::InferFromSettings(settings);
|
||||
configuration.SetEntrypoint("emptyMain");
|
||||
|
||||
RunEngine(shell.get(), std::move(configuration));
|
||||
PumpOneFrame(shell.get(), {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
fml::Status result =
|
||||
shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000));
|
||||
ASSERT_FALSE(result.ok());
|
||||
ASSERT_EQ(result.code(), fml::StatusCode::kDeadlineExceeded);
|
||||
|
||||
DestroyShell(std::move(shell));
|
||||
}
|
||||
|
||||
@ -627,7 +648,9 @@ TEST_F(ShellTest, WaitForFirstFrameTimeout) {
|
||||
RunEngine(shell.get(), std::move(configuration));
|
||||
fml::Status result =
|
||||
shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(10));
|
||||
ASSERT_FALSE(result.ok());
|
||||
ASSERT_EQ(result.code(), fml::StatusCode::kDeadlineExceeded);
|
||||
|
||||
DestroyShell(std::move(shell));
|
||||
}
|
||||
|
||||
@ -650,6 +673,7 @@ TEST_F(ShellTest, WaitForFirstFrameMultiple) {
|
||||
result = shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1));
|
||||
ASSERT_TRUE(result.ok());
|
||||
}
|
||||
|
||||
DestroyShell(std::move(shell));
|
||||
}
|
||||
|
||||
@ -675,10 +699,12 @@ TEST_F(ShellTest, WaitForFirstFrameInlined) {
|
||||
task_runner->PostTask([&shell, &event] {
|
||||
fml::Status result =
|
||||
shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000));
|
||||
ASSERT_FALSE(result.ok());
|
||||
ASSERT_EQ(result.code(), fml::StatusCode::kFailedPrecondition);
|
||||
event.Signal();
|
||||
});
|
||||
ASSERT_FALSE(event.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(1000)));
|
||||
|
||||
DestroyShell(std::move(shell), std::move(task_runners));
|
||||
}
|
||||
|
||||
|
||||
@ -1601,7 +1601,6 @@ TEST_F(EmbedderTest, CustomCompositorMustWorkWithCustomTaskRunner) {
|
||||
event.width = 800;
|
||||
event.height = 600;
|
||||
event.pixel_ratio = 1.0;
|
||||
|
||||
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
|
||||
kSuccess);
|
||||
ASSERT_TRUE(engine.is_valid());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user