未验证 提交 ad8ccf47 编写于 作者: M mikejurka 提交者: GitHub

[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.
上级 c490cb9b
......@@ -49,6 +49,7 @@ 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/fuchsia_layer_unittests.cc
FILE: ../../../flutter/flow/layers/image_filter_layer.cc
FILE: ../../../flutter/flow/layers/image_filter_layer.h
FILE: ../../../flutter/flow/layers/image_filter_layer_unittests.cc
......
......@@ -88,6 +88,7 @@ source_set("flow") {
if (using_fuchsia_sdk) {
public_deps += [
"$fuchsia_sdk_root/fidl:fuchsia.ui.app",
"$fuchsia_sdk_root/fidl:fuchsia.ui.gfx",
"$fuchsia_sdk_root/pkg:scenic_cpp",
]
......@@ -159,6 +160,10 @@ executable("flow_unittests") {
"texture_unittests.cc",
]
if (is_fuchsia) {
sources += [ "layers/fuchsia_layer_unittests.cc" ]
}
deps = [
":flow",
":flow_fixtures",
......@@ -170,6 +175,10 @@ executable("flow_unittests") {
"//third_party/googletest:gtest",
"//third_party/skia",
]
if (is_fuchsia) {
deps += [ "//build/fuchsia/pkg:sys_cpp_testing" ]
}
}
if (is_fuchsia) {
......
......@@ -20,6 +20,7 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id,
void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll");
set_needs_system_composite(true);
context->child_scene_layer_exists_below = true;
// An alpha "hole punch" is required if the frame behind us is not opaque.
if (!context->is_opaque) {
......@@ -49,7 +50,9 @@ void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) {
auto* view_holder = ViewHolder::FromId(layer_id_);
FML_DCHECK(view_holder);
view_holder->UpdateScene(context, offset_, size_, hit_testable_);
view_holder->UpdateScene(context, offset_, size_,
SkScalarRoundToInt(context.alphaf() * 255),
hit_testable_);
}
} // namespace flutter
此差异已折叠。
......@@ -66,6 +66,11 @@ struct PrerollContext {
float total_elevation = 0.0f;
bool has_platform_view = false;
bool is_opaque = true;
#if defined(OS_FUCHSIA)
// True if, during the traversal so far, we have seen a child_scene_layer.
// Informs whether a layer needs to be system composited.
bool child_scene_layer_exists_below = false;
#endif // defined(OS_FUCHSIA)
};
// Represents a single composited layer. Created on the UI thread but then
......
......@@ -83,7 +83,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
context,
SkRRect::MakeRect(
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
SK_ColorTRANSPARENT, SK_AlphaOPAQUE);
SK_ColorTRANSPARENT, SK_AlphaOPAQUE, "flutter::LayerTree");
if (root_layer_->needs_system_composite()) {
root_layer_->UpdateScene(context);
}
......
......@@ -9,11 +9,6 @@
namespace flutter {
// The OpacityLayer has no real "elevation", but we want to avoid Z-fighting
// when using the system compositor. Choose a small but non-zero value for
// this.
constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.01f;
OpacityLayer::OpacityLayer(SkAlpha alpha, const SkPoint& offset)
: alpha_(alpha), offset_(offset) {
// Ensure OpacityLayer has only one direct child.
......@@ -40,8 +35,6 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
SkMatrix child_matrix = matrix;
child_matrix.postTranslate(offset_.fX, offset_.fY);
total_elevation_ = context->total_elevation;
context->total_elevation += kOpacityElevationWhenUsingSystemCompositor;
context->is_opaque = parent_is_opaque && (alpha_ == SK_AlphaOPAQUE);
context->mutators_stack.PushTransform(
SkMatrix::MakeTrans(offset_.fX, offset_.fY));
......@@ -52,17 +45,7 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
context->mutators_stack.Pop();
context->mutators_stack.Pop();
context->is_opaque = parent_is_opaque;
context->total_elevation = total_elevation_;
#if defined(OS_FUCHSIA)
if (needs_system_composite()) {
// When using the system compositor, do not include the offset since we
// are rendering as a separate piece of geometry and the offset will be
// baked into that geometry's transform.
frameRRect_ = SkRRect::MakeRect(paint_bounds());
set_paint_bounds(SkRect::MakeEmpty());
} else
#endif
{
set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
if (!context->has_platform_view && context->raster_cache &&
......@@ -123,36 +106,10 @@ void OpacityLayer::Paint(PaintContext& context) const {
#if defined(OS_FUCHSIA)
void OpacityLayer::UpdateScene(SceneUpdateContext& context) {
FML_DCHECK(needs_system_composite());
TRACE_EVENT0("flutter", "OpacityLayer::UpdateScene");
ContainerLayer* container = GetChildContainer();
FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf.
SceneUpdateContext::Transform transform(
context, SkMatrix::MakeTrans(offset_.fX, offset_.fY));
// 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 PhysicalShapeLayer::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", "cache miss, creating");
// If we can't find an existing retained surface, create one.
SceneUpdateContext::Frame frame(
context, frameRRect_, SK_ColorTRANSPARENT, alpha_,
kOpacityElevationWhenUsingSystemCompositor, total_elevation_, this);
frame.AddPaintLayer(container);
UpdateSceneChildren(context);
float saved_alpha = context.alphaf();
context.set_alphaf(context.alphaf() * (alpha_ / 255.f));
ContainerLayer::UpdateScene(context);
context.set_alphaf(saved_alpha);
}
#endif // defined(OS_FUCHSIA)
......
......@@ -43,7 +43,6 @@ class OpacityLayer : public ContainerLayer {
SkAlpha alpha_;
SkPoint offset_;
SkRRect frameRRect_;
float total_elevation_ = 0.0f;
FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
};
......
......@@ -52,23 +52,31 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context,
context->total_elevation += elevation_;
total_elevation_ = context->total_elevation;
#if defined(OS_FUCHSIA)
child_layer_exists_below_ = context->child_scene_layer_exists_below;
context->child_scene_layer_exists_below = false;
#endif
SkRect child_paint_bounds;
PrerollChildren(context, matrix, &child_paint_bounds);
#if defined(OS_FUCHSIA)
if (child_layer_exists_below_) {
set_needs_system_composite(true);
}
context->child_scene_layer_exists_below =
context->child_scene_layer_exists_below || child_layer_exists_below_;
#endif
context->total_elevation -= elevation_;
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
// 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_,
context->frame_device_pixel_ratio));
#endif // defined(OS_FUCHSIA)
}
}
......@@ -78,30 +86,52 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
FML_DCHECK(needs_system_composite());
TRACE_EVENT0("flutter", "PhysicalShapeLayer::UpdateScene");
// 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 PhysicalShapeLayer::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()->entity_node().AddChild(retained_node);
return;
}
// If there is embedded Fuchsia content in the scene (a ChildSceneLayer),
// PhysicalShapeLayers that appear above the embedded content will be turned
// into their own Scenic layers.
if (child_layer_exists_below_) {
float global_scenic_elevation =
context.GetGlobalElevationForNextScenicLayer();
float local_scenic_elevation =
global_scenic_elevation - context.scenic_elevation();
float z_translation = -local_scenic_elevation;
// 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 PhysicalShapeLayer::Paint.
LayerRasterCacheKey key(unique_id(), context.Matrix());
if (context.HasRetainedNode(key)) {
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
scenic::EntityNode* retained_node = context.GetRetainedNode(key);
FML_DCHECK(context.top_entity());
FML_DCHECK(retained_node->session() == context.session());
// Re-adjust the elevation.
retained_node->SetTranslation(0.f, 0.f, z_translation);
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
// If we can't find an existing retained surface, create one.
SceneUpdateContext::Frame frame(context, frameRRect_, color_, SK_AlphaOPAQUE,
elevation_, total_elevation_, this);
for (auto& layer : layers()) {
if (layer->needs_painting()) {
frame.AddPaintLayer(layer.get());
context.top_entity()->entity_node().AddChild(*retained_node);
return;
}
}
UpdateSceneChildren(context);
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
// If we can't find an existing retained surface, create one.
SceneUpdateContext::Frame frame(context, frameRRect_, SK_ColorTRANSPARENT,
SkScalarRoundToInt(context.alphaf() * 255),
"flutter::PhysicalShapeLayer",
z_translation, this);
frame.AddPaintLayer(this);
// Node: UpdateSceneChildren needs to be called here so that |frame| is
// still in scope (and therefore alive) while UpdateSceneChildren is being
// called.
float scenic_elevation = context.scenic_elevation();
context.set_scenic_elevation(scenic_elevation + local_scenic_elevation);
ContainerLayer::UpdateSceneChildren(context);
context.set_scenic_elevation(scenic_elevation);
} else {
ContainerLayer::UpdateSceneChildren(context);
}
}
#endif // defined(OS_FUCHSIA)
......@@ -110,7 +140,18 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const {
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
FML_DCHECK(needs_painting());
#if defined(OS_FUCHSIA)
// TODO(mikejurka,dworsham,liyl): Re-enable shadow drawing here.
// Shadows are not rendered for PhysicalShapeLayers that exist as separate
// system services; this is to maintain compatibility with the previous
// implementation and has the added benefit of requiring smaller textures,
// since extra space is not needed for the shadows. This behavior might change
// after clients adjust their usage of PhysicalShaperLayer to make elevation
// correlate to desired shadow size.
if (false && !child_layer_exists_below_ && elevation_ != 0) {
#else
if (elevation_ != 0) {
#endif
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_,
SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio);
}
......
......@@ -42,6 +42,9 @@ class PhysicalShapeLayer : public ContainerLayer {
float total_elevation() const { return total_elevation_; }
private:
#if defined(OS_FUCHSIA)
bool child_layer_exists_below_ = false;
#endif
SkColor color_;
SkColor shadow_color_;
float elevation_ = 0.0f;
......
......@@ -126,17 +126,11 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
layer->Preroll(preroll_context(), SkMatrix());
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
// their shadows , so we do not do any painting there.
#if defined(OS_FUCHSIA)
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
EXPECT_FALSE(layer->needs_painting());
EXPECT_TRUE(layer->needs_system_composite());
#else
EXPECT_EQ(layer->paint_bounds(),
PhysicalShapeLayer::ComputeShadowBounds(layer_path.getBounds(),
initial_elevation, 1.0f));
EXPECT_TRUE(layer->needs_painting());
EXPECT_FALSE(layer->needs_system_composite());
#endif
EXPECT_EQ(layer->total_elevation(), initial_elevation);
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
......@@ -187,18 +181,12 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
// On Fuchsia, the system compositor handles all elevated
// PhysicalShapeLayers and their shadows , so we do not do any painting
// there.
#if defined(OS_FUCHSIA)
EXPECT_EQ(layers[i]->paint_bounds(), kEmptyRect);
EXPECT_FALSE(layers[i]->needs_painting());
EXPECT_TRUE(layers[i]->needs_system_composite());
#else
EXPECT_EQ(layers[i]->paint_bounds(),
(PhysicalShapeLayer::ComputeShadowBounds(
layer_path.getBounds(), initial_elevations[i],
1.0f /* pixel_ratio */)));
EXPECT_TRUE(layers[i]->needs_painting());
EXPECT_FALSE(layers[i]->needs_system_composite());
#endif
EXPECT_EQ(layers[i]->total_elevation(), total_elevations[i]);
}
......
......@@ -56,8 +56,12 @@ void TransformLayer::UpdateScene(SceneUpdateContext& context) {
TRACE_EVENT0("flutter", "TransformLayer::UpdateScene");
FML_DCHECK(needs_system_composite());
SceneUpdateContext::Transform transform(context, transform_);
UpdateSceneChildren(context);
if (!transform_.isIdentity()) {
SceneUpdateContext::Transform transform(context, transform_);
UpdateSceneChildren(context);
} else {
UpdateSceneChildren(context);
}
}
#endif // defined(OS_FUCHSIA)
......
......@@ -72,14 +72,9 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
// and possibly for its texture.
// TODO(SCN-137): Need to be able to express the radii as vectors.
scenic::ShapeNode shape_node(session());
scenic::RoundedRectangle shape(
session_, // session
rrect.width(), // width
rrect.height(), // height
rrect.radii(SkRRect::kUpperLeft_Corner).x(), // top_left_radius
rrect.radii(SkRRect::kUpperRight_Corner).x(), // top_right_radius
rrect.radii(SkRRect::kLowerRight_Corner).x(), // bottom_right_radius
rrect.radii(SkRRect::kLowerLeft_Corner).x() // bottom_left_radius
scenic::Rectangle shape(session_, // session
rrect.width(), // width
rrect.height() // height
);
shape_node.SetShape(shape);
shape_node.SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(),
......@@ -222,6 +217,9 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
surfaces_to_submit.emplace_back(std::move(task.surface));
}
paint_tasks_.clear();
alpha_ = 1.f;
topmost_global_scenic_elevation_ = kScenicZElevationBetweenLayers;
scenic_elevation_ = 0.f;
return surfaces_to_submit;
}
......@@ -244,19 +242,22 @@ SceneUpdateContext::Transform::Transform(SceneUpdateContext& context,
: Entity(context),
previous_scale_x_(context.top_scale_x_),
previous_scale_y_(context.top_scale_y_) {
entity_node().SetLabel("flutter::Transform");
if (!transform.isIdentity()) {
// TODO(SCN-192): The perspective and shear components in the matrix
// are not handled correctly.
MatrixDecomposition decomposition(transform);
if (decomposition.IsValid()) {
// Don't allow clients to control the z dimension; we control that
// instead to make sure layers appear in proper order.
entity_node().SetTranslation(decomposition.translation().x(), //
decomposition.translation().y(), //
-decomposition.translation().z() //
0.f //
);
entity_node().SetScale(decomposition.scale().x(), //
decomposition.scale().y(), //
decomposition.scale().z() //
0.f //
);
context.top_scale_x_ *= decomposition.scale().x();
context.top_scale_y_ *= decomposition.scale().y();
......@@ -277,6 +278,7 @@ SceneUpdateContext::Transform::Transform(SceneUpdateContext& context,
: Entity(context),
previous_scale_x_(context.top_scale_x_),
previous_scale_y_(context.top_scale_y_) {
entity_node().SetLabel("flutter::Transform");
if (scale_x != 1.f || scale_y != 1.f || scale_z != 1.f) {
entity_node().SetScale(scale_x, scale_y, scale_z);
context.top_scale_x_ *= scale_x;
......@@ -293,8 +295,8 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
const SkRRect& rrect,
SkColor color,
SkAlpha opacity,
float local_elevation,
float world_elevation,
std::string label,
float z_translation,
Layer* layer)
: Entity(context),
rrect_(rrect),
......@@ -303,23 +305,14 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
opacity_node_(context.session()),
paint_bounds_(SkRect::MakeEmpty()),
layer_(layer) {
const float depth = context.frame_physical_depth();
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().SetLabel(label);
entity_node().SetTranslation(0.f, 0.f, z_translation);
entity_node().AddChild(opacity_node_);
opacity_node_.SetOpacity(opacity_ / 255.0f);
// Scenic currently lacks an API to enable rendering of alpha channel; alpha
// channels are only rendered if there is a OpacityNode higher in the tree
// with opacity != 1. For now, clamp to a infinitesimally smaller value than
// 1, which does not cause visual problems in practice.
opacity_node_.SetOpacity(std::min(kOneMinusEpsilon, opacity_ / 255.0f));
}
SceneUpdateContext::Frame::~Frame() {
......@@ -348,6 +341,7 @@ void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
SceneUpdateContext::Clip::Clip(SceneUpdateContext& context,
const SkRect& shape_bounds)
: Entity(context) {
entity_node().SetLabel("flutter::Clip");
SetEntityNodeClipPlanes(entity_node(), shape_bounds);
}
......
......@@ -5,6 +5,7 @@
#ifndef FLUTTER_FLOW_SCENE_UPDATE_CONTEXT_H_
#define FLUTTER_FLOW_SCENE_UPDATE_CONTEXT_H_
#include <cfloat>
#include <memory>
#include <set>
#include <vector>
......@@ -22,6 +23,15 @@ namespace flutter {
class Layer;
// Scenic currently lacks an API to enable rendering of alpha channel; this only
// happens if there is a OpacityNode higher in the tree with opacity != 1. For
// now, clamp to a infinitesimally smaller value than 1, which does not cause
// visual problems in practice.
constexpr float kOneMinusEpsilon = 1 - FLT_EPSILON;
// How much layers are separated in Scenic z elevation.
constexpr float kScenicZElevationBetweenLayers = 10.f;
class SceneUpdateContext {
public:
class SurfaceProducerSurface {
......@@ -59,7 +69,7 @@ class SceneUpdateContext {
// Query a retained entity node (owned by a retained surface) for retained
// rendering.
virtual bool HasRetainedNode(const LayerRasterCacheKey& key) const = 0;
virtual const scenic::EntityNode& GetRetainedNode(
virtual scenic::EntityNode* GetRetainedNode(
const LayerRasterCacheKey& key) = 0;
virtual void SubmitSurface(
......@@ -105,8 +115,8 @@ class SceneUpdateContext {
const SkRRect& rrect,
SkColor color,
SkAlpha opacity,
float local_elevation = 0.0f,
float parent_elevation = 0.0f,
std::string label,
float z_translation = 0.0f,
Layer* layer = nullptr);
virtual ~Frame();
......@@ -175,10 +185,25 @@ class SceneUpdateContext {
bool HasRetainedNode(const LayerRasterCacheKey& key) const {
return surface_producer_->HasRetainedNode(key);
}
const scenic::EntityNode& GetRetainedNode(const LayerRasterCacheKey& key) {
scenic::EntityNode* GetRetainedNode(const LayerRasterCacheKey& key) {
return surface_producer_->GetRetainedNode(key);
}
// The cumulative alpha value based on all the parent OpacityLayers.
void set_alphaf(float alpha) { alpha_ = alpha; }
float alphaf() { return alpha_; }
// The global scenic elevation at a given point in the traversal.
float scenic_elevation() { return scenic_elevation_; }
void set_scenic_elevation(float elevation) { scenic_elevation_ = elevation; }
float GetGlobalElevationForNextScenicLayer() {
float elevation = topmost_global_scenic_elevation_;
topmost_global_scenic_elevation_ += kScenicZElevationBetweenLayers;
return elevation;
}
private:
struct PaintTask {
std::unique_ptr<SurfaceProducerSurface> surface;
......@@ -236,6 +261,10 @@ class SceneUpdateContext {
float frame_device_pixel_ratio_ =
1.0f; // Ratio between logical and physical pixels.
float alpha_ = 1.0f;
float scenic_elevation_ = 0.f;
float topmost_global_scenic_elevation_ = kScenicZElevationBetweenLayers;
std::vector<PaintTask> paint_tasks_;
FML_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext);
......
......@@ -102,13 +102,17 @@ ViewHolder::ViewHolder(fml::RefPtr<fml::TaskRunner> ui_task_runner,
void ViewHolder::UpdateScene(SceneUpdateContext& context,
const SkPoint& offset,
const SkSize& size,
SkAlpha opacity,
bool hit_testable) {
if (pending_view_holder_token_.value) {
entity_node_ = std::make_unique<scenic::EntityNode>(context.session());
opacity_node_ =
std::make_unique<scenic::OpacityNodeHACK>(context.session());
view_holder_ = std::make_unique<scenic::ViewHolder>(
context.session(), std::move(pending_view_holder_token_),
"Flutter SceneHost");
opacity_node_->AddChild(*entity_node_);
opacity_node_->SetLabel("flutter::ViewHolder");
entity_node_->Attach(*view_holder_);
ui_task_runner_->PostTask(
[bind_callback = std::move(pending_bind_callback_),
......@@ -117,9 +121,11 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context,
});
}
FML_DCHECK(entity_node_);
FML_DCHECK(opacity_node_);
FML_DCHECK(view_holder_);
context.top_entity()->embedder_node().AddChild(*entity_node_);
context.top_entity()->embedder_node().AddChild(*opacity_node_);
opacity_node_->SetOpacity(opacity / 255.0f);
entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f);
entity_node_->SetHitTestBehavior(
hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault
......
......@@ -57,12 +57,14 @@ class ViewHolder {
void UpdateScene(SceneUpdateContext& context,
const SkPoint& offset,
const SkSize& size,
SkAlpha opacity,
bool hit_testable);
private:
fml::RefPtr<fml::TaskRunner> ui_task_runner_;
std::unique_ptr<scenic::EntityNode> entity_node_;
std::unique_ptr<scenic::OpacityNodeHACK> opacity_node_;
std::unique_ptr<scenic::ViewHolder> view_holder_;
fuchsia::ui::views::ViewHolderToken pending_view_holder_token_;
......
......@@ -133,10 +133,11 @@ class VulkanSurface final
// For better safety in retained rendering, Flutter uses a retained
// |EntityNode| associated with the retained surface instead of using the
// retained surface directly. Hence Flutter can't modify the surface during
// retained rendering.
const scenic::EntityNode& GetRetainedNode() {
// retained rendering. However, the node itself is modifiable to be able
// to adjust its position.
scenic::EntityNode* GetRetainedNode() {
used_in_retained_rendering_ = true;
return *retained_node_;
return retained_node_.get();
}
// Check whether the retained surface (and its associated |EntityNode|) is
......
......@@ -43,8 +43,7 @@ class VulkanSurfacePool final {
return retained_surfaces_.find(key) != retained_surfaces_.end();
}
// For |VulkanSurfaceProducer::GetRetainedNode|.
const scenic::EntityNode& GetRetainedNode(
const flutter::LayerRasterCacheKey& key) {
scenic::EntityNode* GetRetainedNode(const flutter::LayerRasterCacheKey& key) {
FML_DCHECK(HasRetainedNode(key));
return retained_surfaces_[key].vk_surface->GetRetainedNode();
}
......
......@@ -49,7 +49,7 @@ class VulkanSurfaceProducer final
}
// |flutter::SceneUpdateContext::GetRetainedNode|
const scenic::EntityNode& GetRetainedNode(
scenic::EntityNode* GetRetainedNode(
const flutter::LayerRasterCacheKey& key) override {
return surface_pool_->GetRetainedNode(key);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册