diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 5715a8445f8031885f0236346d9fdd2c1b7b70bb..720b26d9908aad330c255f8ba15d8c71ac61d9ca 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -117,6 +117,8 @@ FILE: ../../../flutter/flow/skia_gpu_object.cc FILE: ../../../flutter/flow/skia_gpu_object.h FILE: ../../../flutter/flow/texture.cc FILE: ../../../flutter/flow/texture.h +FILE: ../../../flutter/flow/view_holder.cc +FILE: ../../../flutter/flow/view_holder.h FILE: ../../../flutter/flutter_kernel_transformers/lib/track_widget_constructor_locations.dart FILE: ../../../flutter/fml/arraysize.h FILE: ../../../flutter/fml/base32.cc diff --git a/flow/BUILD.gn b/flow/BUILD.gn index 7f7fb87ef7958d95bf7c2519be56c8d74db616ae..23fc36d3a8b844609361d4b49fe49254fa376249 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -77,15 +77,17 @@ source_set("flow") { "layers/child_scene_layer.h", "scene_update_context.cc", "scene_update_context.h", + "view_holder.cc", + "view_holder.h", ] public_deps += [ - "//garnet/public/lib/ui/scenic/cpp", "//sdk/fidl/fuchsia.ui.scenic", + "//sdk/fidl/fuchsia.ui.views", + "//sdk/lib/ui/scenic/cpp", "//topaz/public/dart-pkg/zircon", + "//zircon/public/lib/zx", ] - - public_deps += [ "//zircon/public/lib/zx" ] } } diff --git a/flow/export_node.cc b/flow/export_node.cc index acf7e42da321554e61b1df83eed26d08a875c91b..9895369f4d250c09f6dbacb229777cd3b21e4bcd 100644 --- a/flow/export_node.cc +++ b/flow/export_node.cc @@ -4,81 +4,82 @@ #include "flutter/flow/export_node.h" -#include "flutter/fml/make_copyable.h" +#include "flutter/fml/thread_local.h" + +namespace { + +using ExportNodeBindings = + std::unordered_map>; + +FML_THREAD_LOCAL fml::ThreadLocal tls_export_node_bindings([](intptr_t value) { + delete reinterpret_cast(value); +}); + +} // namespace namespace flow { -ExportNodeHolder::ExportNodeHolder( - fml::RefPtr gpu_task_runner, - fml::RefPtr export_token_handle) - : gpu_task_runner_(std::move(gpu_task_runner)), - export_node_(std::make_unique(export_token_handle)) { - FML_DCHECK(gpu_task_runner_); +ExportNode::ExportNode(zx::eventpair export_token) + : pending_export_token_(std::move(export_token)) { + FML_DCHECK(pending_export_token_); } -void ExportNodeHolder::Bind(SceneUpdateContext& context, - scenic::ContainerNode& container, - const SkPoint& offset, - bool hit_testable) { - export_node_->Bind(context, container, offset, hit_testable); -} +void ExportNode::Create(zx_koid_t id, zx::eventpair export_token) { + // This GPU thread contains at least 1 ViewHolder. Initialize the per-thread + // bindings. + if (tls_export_node_bindings.Get() == 0) { + tls_export_node_bindings.Set( + reinterpret_cast(new ExportNodeBindings())); + } -ExportNodeHolder::~ExportNodeHolder() { - gpu_task_runner_->PostTask( - fml::MakeCopyable([export_node = std::move(export_node_)]() { - export_node->Dispose(true); - })); + auto* bindings = + reinterpret_cast(tls_export_node_bindings.Get()); + FML_DCHECK(bindings); + FML_DCHECK(bindings->find(id) == bindings->end()); + + auto export_node = + std::unique_ptr(new ExportNode(std::move(export_token))); + bindings->emplace(id, std::move(export_node)); } -ExportNode::ExportNode(fml::RefPtr export_token_handle) - : export_token_(export_token_handle->ReleaseHandle()) {} +void ExportNode::Destroy(zx_koid_t id) { + auto* bindings = + reinterpret_cast(tls_export_node_bindings.Get()); + FML_DCHECK(bindings); -ExportNode::~ExportNode() { - // Ensure that we properly released the node. - FML_DCHECK(!node_); - FML_DCHECK(scene_update_context_ == nullptr); + bindings->erase(id); } -void ExportNode::Bind(SceneUpdateContext& context, - scenic::ContainerNode& container, - const SkPoint& offset, - bool hit_testable) { - if (export_token_) { - // Happens first time we bind. - node_.reset(new scenic::EntityNode(container.session())); - node_->Export(std::move(export_token_)); - - // Add ourselves to the context so it can call Dispose() on us if the Scenic - // session is closed. - context.AddExportNode(this); - scene_update_context_ = &context; +ExportNode* ExportNode::FromId(zx_koid_t id) { + auto* bindings = + reinterpret_cast(tls_export_node_bindings.Get()); + if (!bindings) { + return nullptr; } - if (node_) { - container.AddChild(*node_); - node_->SetTranslation(offset.x(), offset.y(), 0.f); - node_->SetHitTestBehavior( - hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault - : fuchsia::ui::gfx::HitTestBehavior::kSuppress); + auto binding = bindings->find(id); + if (binding == bindings->end()) { + return nullptr; } + + return binding->second.get(); } -void ExportNode::Dispose(bool remove_from_scene_update_context) { - // If scene_update_context_ is set, then we should still have a node left to - // dereference. - // If scene_update_context_ is null, then either: - // 1. A node was never created, or - // 2. A node was created but was already dereferenced (i.e. Dispose has - // already been called). - FML_DCHECK(scene_update_context_ || !node_); - - if (remove_from_scene_update_context && scene_update_context_) { - scene_update_context_->RemoveExportNode(this); +void ExportNode::UpdateScene(SceneUpdateContext& context, + const SkPoint& offset, + const SkSize& size, + bool hit_testable) { + if (pending_export_token_) { + export_node_ = std::make_unique(context.session()); + export_node_->Export(std::move(pending_export_token_)); } + FML_DCHECK(export_node_); - scene_update_context_ = nullptr; - export_token_.reset(); - node_ = nullptr; + context.top_entity()->entity_node().AddChild(*export_node_); + export_node_->SetTranslation(offset.x(), offset.y(), -0.1f); + export_node_->SetHitTestBehavior( + hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault + : fuchsia::ui::gfx::HitTestBehavior::kSuppress); } } // namespace flow diff --git a/flow/export_node.h b/flow/export_node.h index 50df904bc411689df115fce395c67d558cdad93d..3b232abdcf18d183398ea4a4c5f0185efe6b7089 100644 --- a/flow/export_node.h +++ b/flow/export_node.h @@ -5,75 +5,42 @@ #ifndef FLUTTER_FLOW_EXPORT_NODE_H_ #define FLUTTER_FLOW_EXPORT_NODE_H_ -#include - +#include #include +#include +#include +#include +#include + +#include -#include "dart-pkg/zircon/sdk_ext/handle.h" #include "flutter/flow/scene_update_context.h" -#include "flutter/fml/build_config.h" #include "flutter/fml/macros.h" -#include "flutter/fml/memory/ref_counted.h" -#include "lib/ui/scenic/cpp/resources.h" -#include "third_party/flutter/fml/task_runner.h" -#include "third_party/skia/include/core/SkPoint.h" namespace flow { -// Wrapper class for ExportNode to use on UI Thread. When ExportNodeHolder is -// destroyed, a task is posted on the Rasterizer thread to dispose the resources -// held by the ExportNode. -class ExportNodeHolder : public fml::RefCountedThreadSafe { - public: - ExportNodeHolder(fml::RefPtr gpu_task_runner, - fml::RefPtr export_token_handle); - ~ExportNodeHolder(); - - // Calls Bind() on the wrapped ExportNode. - void Bind(SceneUpdateContext& context, - scenic::ContainerNode& container, - const SkPoint& offset, - bool hit_testable); - - ExportNode* export_node() { return export_node_.get(); } - - private: - fml::RefPtr gpu_task_runner_; - std::unique_ptr export_node_; - - FML_FRIEND_MAKE_REF_COUNTED(ExportNodeHolder); - FML_FRIEND_REF_COUNTED_THREAD_SAFE(ExportNodeHolder); - FML_DISALLOW_COPY_AND_ASSIGN(ExportNodeHolder); -}; - -// Represents a node which is being exported from the session. -// This object is created on the UI thread but the entity node it contains -// must be created and destroyed by the rasterizer thread. +// Represents a Scenic |ExportNode| resource that exports an |EntityNode| to +// another session. +// +// This object is created and destroyed on the |Rasterizer|'s' thread. class ExportNode { public: - ExportNode(fml::RefPtr export_token_handle); - - ~ExportNode(); + static void Create(zx_koid_t id, zx::eventpair export_token); + static void Destroy(zx_koid_t id); + static ExportNode* FromId(zx_koid_t id); - // Binds the export token to the entity node and adds it as a child of - // the specified container. Must be called on the Rasterizer thread. - void Bind(SceneUpdateContext& context, - scenic::ContainerNode& container, - const SkPoint& offset, - bool hit_testable); + // Creates or updates the contained EntityNode resource using the specified + // |SceneUpdateContext|. + void UpdateScene(SceneUpdateContext& context, + const SkPoint& offset, + const SkSize& size, + bool hit_testable); private: - friend class SceneUpdateContext; - friend class ExportNodeHolder; - - // Cleans up resources held and removes this ExportNode from - // SceneUpdateContext. Must be called on the Rasterizer thread. - void Dispose(bool remove_from_scene_update_context); + ExportNode(zx::eventpair export_token); - // Member variables can only be read or modified on Rasterizer thread. - SceneUpdateContext* scene_update_context_ = nullptr; - zx::eventpair export_token_; - std::unique_ptr node_; + zx::eventpair pending_export_token_; + std::unique_ptr export_node_; FML_DISALLOW_COPY_AND_ASSIGN(ExportNode); }; diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 162a8d1a4df500c0554fcffca3ae64e3a7c05745..a1391da09e18d81b0479344845c81a162d2a81c3 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -4,31 +4,43 @@ #include "flutter/flow/layers/child_scene_layer.h" -namespace flow { +#include "flutter/flow/export_node.h" +#include "flutter/flow/view_holder.h" -ChildSceneLayer::ChildSceneLayer() = default; +namespace flow { -ChildSceneLayer::~ChildSceneLayer() = default; +ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id, + bool use_view_holder, + const SkPoint& offset, + const SkSize& size, + bool hit_testable) + : layer_id_(layer_id), + offset_(offset), + size_(size), + hit_testable_(hit_testable), + use_view_holder_(use_view_holder) {} void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { set_needs_system_composite(true); } void ChildSceneLayer::Paint(PaintContext& context) const { - FXL_NOTREACHED() << "This layer never needs painting."; + FML_NOTREACHED() << "This layer never needs painting."; } void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) { FML_DCHECK(needs_system_composite()); - // TODO(MZ-191): Set clip. - // It's worth asking whether all children should be clipped implicitly - // or whether we should leave this up to the Flutter application to decide. - // In some situations, it might be useful to allow children to draw - // outside of their layout bounds. - if (export_node_holder_) { - context.AddChildScene(export_node_holder_->export_node(), offset_, - hit_testable_); + if (use_view_holder_) { + auto* view_holder = ViewHolder::FromId(layer_id_); + FML_DCHECK(view_holder); + + view_holder->UpdateScene(context, offset_, size_, hit_testable_); + } else { + auto* export_node = ExportNode::FromId(layer_id_); + FML_DCHECK(export_node); + + export_node->UpdateScene(context, offset_, size_, hit_testable_); } } diff --git a/flow/layers/child_scene_layer.h b/flow/layers/child_scene_layer.h index 89fd367a0e69b555b15d3e3b6c03a3d56d0e003f..da7caa4086db5577da16ecf517d5606b2f7baaee 100644 --- a/flow/layers/child_scene_layer.h +++ b/flow/layers/child_scene_layer.h @@ -5,27 +5,24 @@ #ifndef FLUTTER_FLOW_LAYERS_CHILD_SCENE_LAYER_H_ #define FLUTTER_FLOW_LAYERS_CHILD_SCENE_LAYER_H_ -#include "flutter/flow/export_node.h" +#include +#include +#include + #include "flutter/flow/layers/layer.h" +#include "flutter/flow/scene_update_context.h" namespace flow { // Layer that represents an embedded child. class ChildSceneLayer : public Layer { public: - ChildSceneLayer(); - ~ChildSceneLayer() override; - - void set_offset(const SkPoint& offset) { offset_ = offset; } - - void set_size(const SkSize& size) { size_ = size; } - - void set_export_node_holder( - fml::RefPtr export_node_holder) { - export_node_holder_ = std::move(export_node_holder); - } - - void set_hit_testable(bool hit_testable) { hit_testable_ = hit_testable; } + ChildSceneLayer(zx_koid_t layer_id, + bool use_view_holder, + const SkPoint& offset, + const SkSize& size, + bool hit_testable); + ~ChildSceneLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; @@ -34,10 +31,11 @@ class ChildSceneLayer : public Layer { void UpdateScene(SceneUpdateContext& context) override; private: + zx_koid_t layer_id_ = ZX_KOID_INVALID; SkPoint offset_; SkSize size_; - fml::RefPtr export_node_holder_; bool hit_testable_ = true; + bool use_view_holder_ = true; FML_DISALLOW_COPY_AND_ASSIGN(ChildSceneLayer); }; diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index c663d5633e17cd47a40e1652da47aadfb630fbcc..11cda2a4edbd068d8f25c6d5343df39a75761e05 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -4,42 +4,12 @@ #include "flutter/flow/scene_update_context.h" -#include "flutter/flow/export_node.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/matrix_decomposition.h" #include "flutter/fml/trace_event.h" namespace flow { -SceneUpdateContext::SceneUpdateContext(scenic::Session* session, - SurfaceProducer* surface_producer) - : session_(session), surface_producer_(surface_producer) { - FML_DCHECK(surface_producer_ != nullptr); -} - -SceneUpdateContext::~SceneUpdateContext() { - // Release Mozart session resources for all ExportNodes. - for (auto export_node : export_nodes_) { - export_node->Dispose(false); - } -}; - -void SceneUpdateContext::AddChildScene(ExportNode* export_node, - SkPoint offset, - bool hit_testable) { - FML_DCHECK(top_entity_); - - export_node->Bind(*this, top_entity_->entity_node(), offset, hit_testable); -} - -void SceneUpdateContext::AddExportNode(ExportNode* export_node) { - export_nodes_.insert(export_node); // Might already have been added. -} - -void SceneUpdateContext::RemoveExportNode(ExportNode* export_node) { - export_nodes_.erase(export_node); -} - // Helper function to generate clip planes for a scenic::EntityNode. static void SetEntityNodeClipPlanes(scenic::EntityNode* entity_node, const SkRect& bounds) { @@ -79,6 +49,12 @@ static void SetEntityNodeClipPlanes(scenic::EntityNode* entity_node, entity_node->SetClipPlanes(std::move(clip_planes)); } +SceneUpdateContext::SceneUpdateContext(scenic::Session* session, + SurfaceProducer* surface_producer) + : session_(session), surface_producer_(surface_producer) { + FML_DCHECK(surface_producer_ != nullptr); +} + void SceneUpdateContext::CreateFrame( std::unique_ptr entity_node, std::unique_ptr shape_node, @@ -256,21 +232,6 @@ SceneUpdateContext::Entity::~Entity() { context_.top_entity_ = previous_entity_; } -SceneUpdateContext::Clip::Clip(SceneUpdateContext& context, - scenic::Shape& shape, - const SkRect& shape_bounds) - : Entity(context) { - shape_node().SetShape(shape); - shape_node().SetTranslationRH( - shape_bounds.width() * 0.5f + shape_bounds.left(), - shape_bounds.height() * 0.5f + shape_bounds.top(), 0.f); - entity_node().SetClip(0u, true /* clip to self */); - - SetEntityNodeClipPlanes(&entity_node(), shape_bounds); -} - -SceneUpdateContext::Clip::~Clip() = default; - SceneUpdateContext::Transform::Transform(SceneUpdateContext& context, const SkMatrix& transform) : Entity(context), @@ -283,7 +244,7 @@ SceneUpdateContext::Transform::Transform(SceneUpdateContext& context, if (decomposition.IsValid()) { entity_node().SetTranslation(decomposition.translation().x(), // decomposition.translation().y(), // - decomposition.translation().z() // + -decomposition.translation().z() // ); entity_node().SetScale(decomposition.scale().x(), // @@ -347,4 +308,17 @@ void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { paint_bounds_.join(layer->paint_bounds()); } +SceneUpdateContext::Clip::Clip(SceneUpdateContext& context, + scenic::Shape& shape, + const SkRect& shape_bounds) + : Entity(context) { + shape_node().SetShape(shape); + shape_node().SetTranslationRH( + shape_bounds.width() * 0.5f + shape_bounds.left(), + shape_bounds.height() * 0.5f + shape_bounds.top(), 0.f); + entity_node().SetClip(0u, true /* clip to self */); + + SetEntityNodeClipPlanes(&entity_node(), shape_bounds); +} + } // namespace flow diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index def6d441547b5d51629cd2e9eded28996aa239b5..f19c5b8f76e4e50a342c025e9b707aafcda25d29 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -11,7 +11,6 @@ #include "flutter/flow/compositor_context.h" #include "flutter/flow/raster_cache_key.h" -#include "flutter/fml/build_config.h" #include "flutter/fml/compiler_specific.h" #include "flutter/fml/logging.h" #include "flutter/fml/macros.h" @@ -22,8 +21,6 @@ namespace flow { class Layer; -class ExportNodeHolder; -class ExportNode; class SceneUpdateContext { public: @@ -93,14 +90,6 @@ class SceneUpdateContext { std::unique_ptr shape_node_ptr_; }; - class Clip : public Entity { - public: - Clip(SceneUpdateContext& context, - scenic::Shape& shape, - const SkRect& shape_bounds); - ~Clip(); - }; - class Transform : public Entity { public: Transform(SceneUpdateContext& context, const SkMatrix& transform); @@ -139,10 +128,17 @@ class SceneUpdateContext { Layer* layer_; }; + class Clip : public Entity { + public: + Clip(SceneUpdateContext& context, + scenic::Shape& shape, + const SkRect& shape_bounds); + ~Clip() = default; + }; + SceneUpdateContext(scenic::Session* session, SurfaceProducer* surface_producer); - - ~SceneUpdateContext(); + ~SceneUpdateContext() = default; scenic::Session* session() { return session_; } @@ -154,18 +150,6 @@ class SceneUpdateContext { } const fuchsia::ui::gfx::MetricsPtr& metrics() const { return metrics_; } - void AddChildScene(ExportNode* export_node, - SkPoint offset, - bool hit_testable); - - // Adds reference to |export_node| so we can call export_node->Dispose() in - // our destructor. Caller is responsible for calling RemoveExportNode() before - // |export_node| is destroyed. - void AddExportNode(ExportNode* export_node); - - // Removes reference to |export_node|. - void RemoveExportNode(ExportNode* export_node); - // 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 @@ -243,9 +227,6 @@ class SceneUpdateContext { std::vector paint_tasks_; - // Save ExportNodes so we can dispose them in our destructor. - std::set export_nodes_; - FML_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext); }; diff --git a/flow/view_holder.cc b/flow/view_holder.cc new file mode 100644 index 0000000000000000000000000000000000000000..129f843724da55341f6d10178b63e188048db6db --- /dev/null +++ b/flow/view_holder.cc @@ -0,0 +1,151 @@ +// 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/view_holder.h" + +#include "flutter/fml/thread_local.h" + +namespace { + +using ViewHolderBindings = + std::unordered_map>; + +FML_THREAD_LOCAL fml::ThreadLocal tls_view_holder_bindings([](intptr_t value) { + delete reinterpret_cast(value); +}); + +fuchsia::ui::gfx::ViewProperties ToViewProperties(float width, + float height, + float insetTop, + float insetRight, + float insetBottom, + float insetLeft, + bool focusable) { + return fuchsia::ui::gfx::ViewProperties({ + .bounding_box = fuchsia::ui::gfx::BoundingBox({ + .min = fuchsia::ui::gfx::vec3({ + .x = 0.f, + .y = 0.f, + .z = -1000.f, + }), + .max = fuchsia::ui::gfx::vec3({.x = width, .y = height, .z = 0.f}), + }), + .inset_from_min = fuchsia::ui::gfx::vec3({ + .x = insetLeft, + .y = insetTop, + .z = 0.f, + }), + .inset_from_max = fuchsia::ui::gfx::vec3({ + .x = insetRight, + .y = insetBottom, + .z = 0.f, + }), + .focus_change = focusable, + }); +} + +} // namespace + +namespace flow { + +ViewHolder::ViewHolder(fml::RefPtr ui_task_runner, + fuchsia::ui::views::ViewHolderToken view_holder_token, + BindCallback on_bind_callback) + : pending_view_holder_token_(std::move(view_holder_token)), + ui_task_runner_(std::move(ui_task_runner)), + pending_bind_callback_(std::move(on_bind_callback)) { + FML_DCHECK(pending_view_holder_token_.value); + FML_DCHECK(ui_task_runner_); +} + +void ViewHolder::Create(zx_koid_t id, + fml::RefPtr ui_task_runner, + fuchsia::ui::views::ViewHolderToken view_holder_token, + BindCallback on_bind_callback) { + // This GPU thread contains at least 1 ViewHolder. Initialize the per-thread + // bindings. + if (tls_view_holder_bindings.Get() == 0) { + tls_view_holder_bindings.Set( + reinterpret_cast(new ViewHolderBindings())); + } + + auto* bindings = + reinterpret_cast(tls_view_holder_bindings.Get()); + FML_DCHECK(bindings); + FML_DCHECK(bindings->find(id) == bindings->end()); + + auto view_holder = std::unique_ptr( + new ViewHolder(std::move(ui_task_runner), std::move(view_holder_token), + std::move(on_bind_callback))); + bindings->emplace(id, std::move(view_holder)); +} + +void ViewHolder::Destroy(zx_koid_t id) { + auto* bindings = + reinterpret_cast(tls_view_holder_bindings.Get()); + FML_DCHECK(bindings); + + bindings->erase(id); +} + +ViewHolder* ViewHolder::FromId(zx_koid_t id) { + auto* bindings = + reinterpret_cast(tls_view_holder_bindings.Get()); + if (!bindings) { + return nullptr; + } + + auto binding = bindings->find(id); + if (binding == bindings->end()) { + return nullptr; + } + + return binding->second.get(); +} + +void ViewHolder::UpdateScene(SceneUpdateContext& context, + const SkPoint& offset, + const SkSize& size, + bool hit_testable) { + if (pending_view_holder_token_.value) { + entity_node_ = std::make_unique(context.session()); + view_holder_ = std::make_unique( + context.session(), std::move(pending_view_holder_token_), + "Flutter SceneHost"); + + entity_node_->Attach(*view_holder_); + ui_task_runner_->PostTask( + [bind_callback = std::move(pending_bind_callback_), + view_holder_id = view_holder_->id()]() { + bind_callback(view_holder_id); + }); + } + FML_DCHECK(entity_node_); + FML_DCHECK(view_holder_); + + context.top_entity()->entity_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_properties_) { + view_holder_->SetViewProperties(std::move(pending_properties_)); + + has_pending_properties_ = false; + } +} + +void ViewHolder::SetProperties(double width, + double height, + double insetTop, + double insetRight, + double insetBottom, + double insetLeft, + bool focusable) { + pending_properties_ = ToViewProperties(width, height, insetTop, insetRight, + insetBottom, insetLeft, focusable); + has_pending_properties_ = true; +} + +} // namespace flow diff --git a/flow/view_holder.h b/flow/view_holder.h new file mode 100644 index 0000000000000000000000000000000000000000..2695ab86c66958f2d8c4e0fb4e5c319fbfc70755 --- /dev/null +++ b/flow/view_holder.h @@ -0,0 +1,75 @@ +// 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_VIEW_HOLDER_H_ +#define FLUTTER_FLOW_VIEW_HOLDER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "flutter/flow/scene_update_context.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/ref_counted.h" +#include "flutter/fml/task_runner.h" + +namespace flow { + +// Represents a Scenic |ViewHolder| resource that imports a |View| from another +// session. +// +// This object is created and destroyed on the |Rasterizer|'s thread. +class ViewHolder { + public: + using BindCallback = std::function; + + static void Create(zx_koid_t id, + fml::RefPtr ui_task_runner, + fuchsia::ui::views::ViewHolderToken view_holder_token, + BindCallback on_bind_callback); + static void Destroy(zx_koid_t id); + static ViewHolder* FromId(zx_koid_t id); + + // Sets the properties of the child view by issuing a Scenic command. + void SetProperties(double width, + double height, + double insetTop, + double insetRight, + double insetBottom, + double insetLeft, + bool focusable); + + // Creates or updates the contained ViewHolder resource using the specified + // |SceneUpdateContext|. + void UpdateScene(SceneUpdateContext& context, + const SkPoint& offset, + const SkSize& size, + bool hit_testable); + + private: + ViewHolder(fml::RefPtr ui_task_runner, + fuchsia::ui::views::ViewHolderToken view_holder_token, + BindCallback on_bind_callback); + + fuchsia::ui::gfx::ViewProperties pending_properties_; + fuchsia::ui::views::ViewHolderToken pending_view_holder_token_; + fml::RefPtr ui_task_runner_; + std::unique_ptr entity_node_; + std::unique_ptr view_holder_; + BindCallback pending_bind_callback_; + bool has_pending_properties_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(ViewHolder); +}; + +} // namespace flow + +#endif // FLUTTER_FLOW_VIEW_HOLDER_H_ diff --git a/fml/command_line.h b/fml/command_line.h index e1d06e6e6bed597f5b22ab0443ab3300b0e25c4b..ea25151641dddf9055a57c9aabf1428112e7074a 100644 --- a/fml/command_line.h +++ b/fml/command_line.h @@ -33,8 +33,8 @@ // mostly explains a.), c. it makes parsing "subcommands", like "my_program // --flag_for_my_program subcommand --flag_for_subcommand" saner. -#ifndef LIB_FXL_COMMAND_LINE_H_ -#define LIB_FXL_COMMAND_LINE_H_ +#ifndef LIB_FML_COMMAND_LINE_H_ +#define LIB_FML_COMMAND_LINE_H_ #include @@ -239,4 +239,4 @@ std::vector CommandLineToArgv(const CommandLine& command_line); } // namespace fml -#endif // LIB_FXL_COMMAND_LINE_H_ +#endif // LIB_FML_COMMAND_LINE_H_ diff --git a/lib/stub_ui/lib/compositing.dart b/lib/stub_ui/lib/compositing.dart index 021977a761f29731d3f4278c7a0a051664f440c8..01257b99fd0598c05aedae9d0aa0aca4cb4ae0bc 100644 --- a/lib/stub_ui/lib/compositing.dart +++ b/lib/stub_ui/lib/compositing.dart @@ -318,6 +318,11 @@ class SceneHost { /// /// The scene host takes ownership of the provided export token handle. SceneHost(dynamic exportTokenHandle); + SceneHost.fromViewHolderToken( + dynamic viewHolderTokenHandle, + void Function() viewConnectedCallback, + void Function() viewDisconnectedCallback, + void Function(bool) viewStateChangedCallback); /// Releases the resources associated with the child scene host. /// @@ -325,4 +330,17 @@ class SceneHost { void dispose() { throw UnimplementedError(); } + + /// Set properties on the linked scene. These properties include its bounds, + /// as well as whether it can be the target of focus events or not. + void setProperties( + double width, + double height, + double insetTop, + double insetRight, + double insetBottom, + double insetLeft, + bool focusable) { + throw UnimplementedError(); + } } diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index cba7632ce0b6048f279c2a3d16db9566a3cd42ac..51dd35ccfbea81b7588ab5b23d7b90b1db0f90f4 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -8,8 +8,6 @@ source_set("ui") { "compositing/scene.h", "compositing/scene_builder.cc", "compositing/scene_builder.h", - "compositing/scene_host.cc", - "compositing/scene_host.h", "dart_runtime_hooks.cc", "dart_runtime_hooks.h", "dart_ui.cc", @@ -115,11 +113,17 @@ source_set("ui") { "//third_party/skia", "//third_party/tonic", ] - if (is_fuchsia) { - deps += [ "//topaz/public/dart-pkg/zircon" ] - } public_deps = [ "$flutter_root/third_party/txt", ] + + if (is_fuchsia) { + sources += [ + "compositing/scene_host.cc", + "compositing/scene_host.h", + ] + + deps += [ "//topaz/public/dart-pkg/zircon" ] + } } diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 9eb7c317485b0ec0001b61f44d6ffd193db9841d..8b3f98c821106656af25ce3ff1a60848bc010059 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -376,10 +376,37 @@ class SceneHost extends NativeFieldWrapperClass2 { SceneHost(dynamic exportTokenHandle) { _constructor(exportTokenHandle); } + SceneHost.fromViewHolderToken( + dynamic viewHolderTokenHandle, + void Function() viewConnectedCallback, + void Function() viewDisconnectedCallback, + void Function(bool) viewStateChangedCallback) { + _constructorViewHolderToken(viewHolderTokenHandle, viewConnectedCallback, + viewDisconnectedCallback, viewStateChangedCallback); + } + void _constructor(dynamic exportTokenHandle) native 'SceneHost_constructor'; + void + _constructorViewHolderToken( + dynamic viewHolderTokenHandle, + void Function() viewConnectedCallback, + void Function() viewDisconnectedCallback, + void Function(bool) viewStateChangedCallback) + native 'SceneHost_constructorViewHolderToken'; /// Releases the resources associated with the child scene host. /// /// After calling this function, the child scene host cannot be used further. void dispose() native 'SceneHost_dispose'; + + /// Set properties on the linked scene. These properties include its bounds, + /// as well as whether it can be the target of focus events or not. + void setProperties( + double width, + double height, + double insetTop, + double insetRight, + double insetBottom, + double insetLeft, + bool focusable) native 'SceneHost_setProperties'; } diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 39eabaaba859862ebdfff0e7b5b8832d413dff7c..c028196969c2dd24df7b2bbf7d41491724395e04 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -5,9 +5,6 @@ #include "flutter/lib/ui/compositing/scene_builder.h" #include "flutter/flow/layers/backdrop_filter_layer.h" -#if defined(OS_FUCHSIA) -#include "flutter/flow/layers/child_scene_layer.h" -#endif #include "flutter/flow/layers/clip_path_layer.h" #include "flutter/flow/layers/clip_rect_layer.h" #include "flutter/flow/layers/clip_rrect_layer.h" @@ -34,6 +31,10 @@ #include "third_party/tonic/dart_binding_macros.h" #include "third_party/tonic/dart_library_natives.h" +#if defined(OS_FUCHSIA) +#include "flutter/flow/layers/child_scene_layer.h" +#endif + namespace blink { static void SceneBuilder_constructor(Dart_NativeArguments args) { @@ -58,7 +59,6 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder); V(SceneBuilder, addRetained) \ V(SceneBuilder, addPicture) \ V(SceneBuilder, addTexture) \ - V(SceneBuilder, addChildScene) \ V(SceneBuilder, addPerformanceOverlay) \ V(SceneBuilder, setRasterizerTracingThreshold) \ V(SceneBuilder, setCheckerboardOffscreenLayers) \ @@ -66,11 +66,18 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder); V(SceneBuilder, build) FOR_EACH_BINDING(DART_NATIVE_CALLBACK) +#if defined(OS_FUCHSIA) +DART_NATIVE_CALLBACK(SceneBuilder, addChildScene) +#endif void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) { - natives->Register( - {{"SceneBuilder_constructor", SceneBuilder_constructor, 1, true}, - FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); + natives->Register({ + {"SceneBuilder_constructor", SceneBuilder_constructor, 1, true}, + FOR_EACH_BINDING(DART_REGISTER_NATIVE) +#if defined(OS_FUCHSIA) + DART_REGISTER_NATIVE(SceneBuilder, addChildScene) +#endif + }); } SceneBuilder::SceneBuilder() = default; @@ -251,24 +258,22 @@ void SceneBuilder::addPlatformView(double dx, current_layer_->Add(std::move(layer)); } +#if defined(OS_FUCHSIA) void SceneBuilder::addChildScene(double dx, double dy, double width, double height, SceneHost* sceneHost, bool hitTestable) { -#if defined(OS_FUCHSIA) if (!current_layer_) { return; } - auto layer = std::make_unique(); - layer->set_offset(SkPoint::Make(dx, dy)); - layer->set_size(SkSize::Make(width, height)); - layer->set_export_node_holder(sceneHost->export_node_holder()); - layer->set_hit_testable(hitTestable); + auto layer = std::make_unique( + sceneHost->id(), sceneHost->use_view_holder(), SkPoint::Make(dx, dy), + SkSize::Make(width, height), hitTestable); current_layer_->Add(std::move(layer)); -#endif // defined(OS_FUCHSIA) } +#endif // defined(OS_FUCHSIA) void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, double left, diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index 2f59be6510f4fe1a19ba054944d0b2e4ef225f97..84723049a9160b72ebeca05875b96d0b6f906385 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -6,11 +6,11 @@ #define FLUTTER_LIB_UI_COMPOSITING_SCENE_BUILDER_H_ #include + #include #include #include "flutter/lib/ui/compositing/scene.h" -#include "flutter/lib/ui/compositing/scene_host.h" #include "flutter/lib/ui/dart_wrapper.h" #include "flutter/lib/ui/painting/engine_layer.h" #include "flutter/lib/ui/painting/image_filter.h" @@ -20,6 +20,10 @@ #include "flutter/lib/ui/painting/shader.h" #include "third_party/tonic/typed_data/float64_list.h" +#if defined(OS_FUCHSIA) +#include "flutter/lib/ui/compositing/scene_host.h" +#endif + namespace blink { class SceneBuilder : public RefCountedDartWrappable { @@ -83,12 +87,14 @@ class SceneBuilder : public RefCountedDartWrappable { double height, int64_t viewId); +#if defined(OS_FUCHSIA) void addChildScene(double dx, double dy, double width, double height, SceneHost* sceneHost, bool hitTestable); +#endif void setRasterizerTracingThreshold(uint32_t frameInterval); diff --git a/lib/ui/compositing/scene_host.cc b/lib/ui/compositing/scene_host.cc index d0441354949c4a525c8aa516d4f7567cf09851fa..75f40449f2dedc640e5b18e45c8bb4c4596d8526 100644 --- a/lib/ui/compositing/scene_host.cc +++ b/lib/ui/compositing/scene_host.cc @@ -4,52 +4,226 @@ #include "flutter/lib/ui/compositing/scene_host.h" +#include +#include +#include +#include +#include +#include + +#include "flutter/flow/export_node.h" +#include "flutter/flow/view_holder.h" +#include "flutter/fml/thread_local.h" #include "flutter/lib/ui/ui_dart_state.h" -#include "third_party/tonic/dart_args.h" -#include "third_party/tonic/dart_binding_macros.h" -#include "third_party/tonic/dart_library_natives.h" -#ifdef OS_FUCHSIA -#include "dart-pkg/zircon/sdk_ext/handle.h" -#endif +namespace { -namespace blink { +using SceneHostBindings = std::unordered_map; + +FML_THREAD_LOCAL fml::ThreadLocal tls_scene_host_bindings([](intptr_t value) { + delete reinterpret_cast(value); +}); + +void SceneHost_constructor(Dart_NativeArguments args) { + tonic::DartCallConstructor(&blink::SceneHost::Create, args); +} + +void SceneHost_constructorViewHolderToken(Dart_NativeArguments args) { + // This UI thread / Isolate contains at least 1 SceneHost. Initialize the + // per-Isolate bindings. + if (tls_scene_host_bindings.Get() == 0) { + tls_scene_host_bindings.Set( + reinterpret_cast(new SceneHostBindings())); + } + + tonic::DartCallConstructor(&blink::SceneHost::CreateViewHolder, args); +} + +blink::SceneHost* GetSceneHost(scenic::ResourceId id) { + auto* bindings = + reinterpret_cast(tls_scene_host_bindings.Get()); + FML_DCHECK(bindings); + + auto binding = bindings->find(id); + if (binding != bindings->end()) { + return binding->second; + } -static void SceneHost_constructor(Dart_NativeArguments args) { - DartCallConstructor(&SceneHost::create, args); + return nullptr; } +void InvokeDartClosure(tonic::DartPersistentValue* closure) { + if (closure) { + std::shared_ptr dart_state = closure->dart_state().lock(); + if (!dart_state) { + return; + } + + tonic::DartState::Scope scope(dart_state); + tonic::DartInvoke(closure->value(), {}); + } +} + +template +void InvokeDartFunction(tonic::DartPersistentValue* function, T& arg) { + if (function) { + std::shared_ptr dart_state = + function->dart_state().lock(); + if (!dart_state) { + return; + } + + tonic::DartState::Scope scope(dart_state); + tonic::DartInvoke(function->value(), {tonic::ToDart(arg)}); + } +} + +} // namespace + +namespace blink { + IMPLEMENT_WRAPPERTYPEINFO(ui, SceneHost); -#define FOR_EACH_BINDING(V) V(SceneHost, dispose) +#define FOR_EACH_BINDING(V) \ + V(SceneHost, dispose) \ + V(SceneHost, setProperties) FOR_EACH_BINDING(DART_NATIVE_CALLBACK) void SceneHost::RegisterNatives(tonic::DartLibraryNatives* natives) { natives->Register({{"SceneHost_constructor", SceneHost_constructor, 2, true}, FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); + natives->Register({{"SceneHost_constructorViewHolderToken", + SceneHost_constructorViewHolderToken, 5, true}, + FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); } -#if defined(OS_FUCHSIA) -fml::RefPtr SceneHost::create( - fml::RefPtr export_token_handle) { - return fml::MakeRefCounted(export_token_handle); +fml::RefPtr SceneHost::Create( + fml::RefPtr exportTokenHandle) { + return fml::MakeRefCounted(exportTokenHandle); } -SceneHost::SceneHost(fml::RefPtr export_token_handle) { - export_node_holder_ = fml::MakeRefCounted( - blink::UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner(), - export_token_handle); +fml::RefPtr SceneHost::CreateViewHolder( + fml::RefPtr viewHolderTokenHandle, + Dart_Handle viewConnectedCallback, + Dart_Handle viewDisconnectedCallback, + Dart_Handle viewStateChangedCallback) { + return fml::MakeRefCounted( + viewHolderTokenHandle, viewConnectedCallback, viewDisconnectedCallback, + viewStateChangedCallback); } -#else -fml::RefPtr SceneHost::create(Dart_Handle export_token_handle) { - return fml::MakeRefCounted(export_token_handle); + +SceneHost::SceneHost(fml::RefPtr exportTokenHandle) + : gpu_task_runner_( + UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner()), + id_(fsl::GetKoid(exportTokenHandle->handle())), + use_view_holder_(false) { + gpu_task_runner_->PostTask( + [id = id_, handle = std::move(exportTokenHandle)]() { + auto export_token = zx::eventpair(handle->ReleaseHandle()); + flow::ExportNode::Create(id, std::move(export_token)); + }); +} + +SceneHost::SceneHost(fml::RefPtr viewHolderTokenHandle, + Dart_Handle viewConnectedCallback, + Dart_Handle viewDisconnectedCallback, + Dart_Handle viewStateChangedCallback) + : gpu_task_runner_( + UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner()), + id_(fsl::GetKoid(viewHolderTokenHandle->handle())), + use_view_holder_(true) { + if (Dart_IsClosure(viewConnectedCallback)) { + view_connected_callback_ = std::make_unique( + UIDartState::Current(), viewConnectedCallback); + } + if (Dart_IsClosure(viewDisconnectedCallback)) { + view_disconnected_callback_ = std::make_unique( + UIDartState::Current(), viewDisconnectedCallback); + } + if (Dart_IsClosure(viewConnectedCallback)) { + view_state_changed_callback_ = std::make_unique( + UIDartState::Current(), viewStateChangedCallback); + } + + auto bind_callback = [scene_host = this](scenic::ResourceId id) { + auto* bindings = + reinterpret_cast(tls_scene_host_bindings.Get()); + FML_DCHECK(bindings); + FML_DCHECK(bindings->find(id) == bindings->end()); + + bindings->emplace(std::make_pair(id, scene_host)); + }; + + auto ui_task_runner = + UIDartState::Current()->GetTaskRunners().GetUITaskRunner(); + gpu_task_runner_->PostTask([id = id_, + ui_task_runner = std::move(ui_task_runner), + handle = std::move(viewHolderTokenHandle), + bind_callback = std::move(bind_callback)]() { + auto view_holder_token = + scenic::ToViewHolderToken(zx::eventpair(handle->ReleaseHandle())); + flow::ViewHolder::Create(id, std::move(ui_task_runner), + std::move(view_holder_token), + std::move(bind_callback)); + }); +} + +SceneHost::~SceneHost() { + if (use_view_holder_) { + auto* bindings = + reinterpret_cast(tls_scene_host_bindings.Get()); + FML_DCHECK(bindings); + bindings->erase(id_); + + gpu_task_runner_->PostTask([id = id_]() { flow::ViewHolder::Destroy(id); }); + } else { + gpu_task_runner_->PostTask([id = id_]() { flow::ExportNode::Destroy(id); }); + } +} + +void SceneHost::OnViewConnected(scenic::ResourceId id) { + auto* scene_host = GetSceneHost(id); + + if (scene_host) { + InvokeDartClosure(scene_host->view_connected_callback_.get()); + } +} + +void SceneHost::OnViewDisconnected(scenic::ResourceId id) { + auto* scene_host = GetSceneHost(id); + + if (scene_host) { + InvokeDartClosure(scene_host->view_disconnected_callback_.get()); + } } -SceneHost::SceneHost(Dart_Handle export_token_handle) {} -#endif +void SceneHost::OnViewStateChanged(scenic::ResourceId id, bool state) { + auto* scene_host = GetSceneHost(id); -SceneHost::~SceneHost() {} + if (scene_host) { + InvokeDartFunction(scene_host->view_state_changed_callback_.get(), state); + } +} + +void SceneHost::setProperties(double width, + double height, + double insetTop, + double insetRight, + double insetBottom, + double insetLeft, + bool focusable) { + FML_DCHECK(use_view_holder_); + + gpu_task_runner_->PostTask([id = id_, width, height, insetTop, insetRight, + insetBottom, insetLeft, focusable]() { + auto* view_holder = flow::ViewHolder::FromId(id); + FML_DCHECK(view_holder); + + view_holder->SetProperties(width, height, insetTop, insetRight, insetBottom, + insetLeft, focusable); + }); +} void SceneHost::dispose() { ClearDartWrapper(); diff --git a/lib/ui/compositing/scene_host.h b/lib/ui/compositing/scene_host.h index cad141d0941baa9c094073a90caaed68a1d467d1..04f4ffa824718f0bdde560a38c30e6c3493d56d5 100644 --- a/lib/ui/compositing/scene_host.h +++ b/lib/ui/compositing/scene_host.h @@ -5,19 +5,17 @@ #ifndef FLUTTER_LIB_UI_COMPOSITING_SCENE_HOST_H_ #define FLUTTER_LIB_UI_COMPOSITING_SCENE_HOST_H_ +#include +#include #include +#include +#include +#include -#include "flutter/fml/build_config.h" +#include "flutter/fml/memory/ref_counted.h" +#include "flutter/fml/task_runner.h" #include "flutter/lib/ui/dart_wrapper.h" -#if defined(OS_FUCHSIA) -#include "flutter/flow/export_node.h" -#endif - -namespace tonic { -class DartLibraryNatives; -} // namespace tonic - namespace blink { class SceneHost : public RefCountedDartWrappable { @@ -25,35 +23,45 @@ class SceneHost : public RefCountedDartWrappable { FML_FRIEND_MAKE_REF_COUNTED(SceneHost); public: -#if defined(OS_FUCHSIA) - static fml::RefPtr create( - fml::RefPtr export_token_handle); -#else - static fml::RefPtr create(Dart_Handle export_token_handle); -#endif - ~SceneHost() override; -#if defined(OS_FUCHSIA) - const fml::RefPtr& export_node_holder() const { - return export_node_holder_; - } -#endif - - void dispose(); - static void RegisterNatives(tonic::DartLibraryNatives* natives); + static fml::RefPtr Create( + fml::RefPtr exportTokenHandle); + static fml::RefPtr CreateViewHolder( + fml::RefPtr viewHolderTokenHandle, + Dart_Handle viewConnectedCallback, + Dart_Handle viewDisconnectedCallback, + Dart_Handle viewStateChangedCallback); + static void OnViewConnected(scenic::ResourceId id); + static void OnViewDisconnected(scenic::ResourceId id); + static void OnViewStateChanged(scenic::ResourceId id, bool state); + + zx_koid_t id() const { return id_; } + bool use_view_holder() const { return use_view_holder_; } + + void setProperties(double width, + double height, + double insetTop, + double insetRight, + double insetBottom, + double insetLeft, + bool focusable); + void dispose(); private: -#if defined(OS_FUCHSIA) - fml::RefPtr export_node_holder_; -#endif - -#if defined(OS_FUCHSIA) - explicit SceneHost(fml::RefPtr export_token_handle); -#else - explicit SceneHost(Dart_Handle export_token_handle); -#endif + explicit SceneHost(fml::RefPtr exportTokenHandle); + SceneHost(fml::RefPtr viewHolderTokenHandle, + Dart_Handle viewConnectedCallback, + Dart_Handle viewDisconnectedCallback, + Dart_Handle viewStateChangedCallback); + + fml::RefPtr gpu_task_runner_; + std::unique_ptr view_connected_callback_; + std::unique_ptr view_disconnected_callback_; + std::unique_ptr view_state_changed_callback_; + zx_koid_t id_ = ZX_KOID_INVALID; + bool use_view_holder_ = false; }; } // namespace blink diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index df5bc9713f55f9d56abc1a8c1d44617bd018f8be..514813017978d31487513ad3f9b15498a062f131 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -32,6 +32,10 @@ #include "third_party/tonic/converter/dart_converter.h" #include "third_party/tonic/logging/dart_error.h" +#if defined(OS_FUCHSIA) +#include "flutter/lib/ui/compositing/scene_host.h" +#endif + using tonic::ToDart; namespace blink { @@ -85,12 +89,14 @@ void DartUI::InitForGlobal() { PictureRecorder::RegisterNatives(g_natives); Scene::RegisterNatives(g_natives); SceneBuilder::RegisterNatives(g_natives); - SceneHost::RegisterNatives(g_natives); SemanticsUpdate::RegisterNatives(g_natives); SemanticsUpdateBuilder::RegisterNatives(g_natives); Versions::RegisterNatives(g_natives); Vertices::RegisterNatives(g_natives); Window::RegisterNatives(g_natives); +#if defined(OS_FUCHSIA) + SceneHost::RegisterNatives(g_natives); +#endif // Secondary isolates do not provide UI-related APIs. g_natives_secondary = new tonic::DartLibraryNatives();