未验证 提交 07e2520d 编写于 作者: D David Worsham 提交者: GitHub

fuchsia: create new flutter_runner render path (#19584)

上级 80a1cac4
...@@ -1162,6 +1162,8 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/engine.h ...@@ -1162,6 +1162,8 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/engine.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/flutter_runner_fakes.h FILE: ../../../flutter/shell/platform/fuchsia/flutter/flutter_runner_fakes.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/flutter_runner_product_configuration.cc FILE: ../../../flutter/shell/platform/fuchsia/flutter/flutter_runner_product_configuration.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/flutter_runner_product_configuration.h FILE: ../../../flutter/shell/platform/fuchsia/flutter/flutter_runner_product_configuration.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl.cc FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl.h FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl_unittest.cc FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_intl_unittest.cc
......
...@@ -53,12 +53,12 @@ template("runner_sources") { ...@@ -53,12 +53,12 @@ template("runner_sources") {
"accessibility_bridge.h", "accessibility_bridge.h",
"component.cc", "component.cc",
"component.h", "component.h",
"compositor_context.cc",
"compositor_context.h",
"engine.cc", "engine.cc",
"engine.h", "engine.h",
"flutter_runner_product_configuration.cc", "flutter_runner_product_configuration.cc",
"flutter_runner_product_configuration.h", "flutter_runner_product_configuration.h",
"fuchsia_external_view_embedder.cc",
"fuchsia_external_view_embedder.h",
"fuchsia_intl.cc", "fuchsia_intl.cc",
"fuchsia_intl.h", "fuchsia_intl.h",
"isolate_configurator.cc", "isolate_configurator.cc",
...@@ -92,6 +92,12 @@ template("runner_sources") { ...@@ -92,6 +92,12 @@ template("runner_sources") {
"vulkan_surface_producer.cc", "vulkan_surface_producer.cc",
"vulkan_surface_producer.h", "vulkan_surface_producer.h",
] ]
if (flutter_enable_legacy_fuchsia_embedder) {
sources += [
"compositor_context.cc",
"compositor_context.h",
]
}
public_configs = runner_configs public_configs = runner_configs
......
...@@ -54,6 +54,7 @@ constexpr char kDataKey[] = "data"; ...@@ -54,6 +54,7 @@ constexpr char kDataKey[] = "data";
constexpr char kAssetsKey[] = "assets"; constexpr char kAssetsKey[] = "assets";
constexpr char kTmpPath[] = "/tmp"; constexpr char kTmpPath[] = "/tmp";
constexpr char kServiceRootPath[] = "/svc"; constexpr char kServiceRootPath[] = "/svc";
constexpr char kRunnerConfigPath[] = "/config/data/flutter_runner_config";
// static // static
void Application::ParseProgramMetadata( void Application::ParseProgramMetadata(
...@@ -346,11 +347,13 @@ Application::Application( ...@@ -346,11 +347,13 @@ Application::Application(
} }
} }
// Load and use product-specific configuration, if it exists. // Load and use runner-specific configuration, if it exists.
std::string json_string; std::string json_string;
if (dart_utils::ReadFileToString( if (dart_utils::ReadFileToString(kRunnerConfigPath, &json_string)) {
"/config/data/frame_scheduling_performance_values", &json_string)) {
product_config_ = FlutterRunnerProductConfiguration(json_string); product_config_ = FlutterRunnerProductConfiguration(json_string);
} else {
FML_LOG(WARNING) << "Failed to load runner configuration from "
<< kRunnerConfigPath << "; using default config values.";
} }
#if defined(DART_PRODUCT) #if defined(DART_PRODUCT)
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <zircon/status.h> #include <zircon/status.h>
#include "../runtime/dart/utils/files.h" #include "../runtime/dart/utils/files.h"
#include "compositor_context.h"
#include "flutter/common/task_runners.h" #include "flutter/common/task_runners.h"
#include "flutter/fml/make_copyable.h" #include "flutter/fml/make_copyable.h"
#include "flutter/fml/synchronization/waitable_event.h" #include "flutter/fml/synchronization/waitable_event.h"
...@@ -16,13 +15,20 @@ ...@@ -16,13 +15,20 @@
#include "flutter/runtime/dart_vm_lifecycle.h" #include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/rasterizer.h" #include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/run_configuration.h" #include "flutter/shell/common/run_configuration.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "flutter_runner_product_configuration.h" #include "flutter_runner_product_configuration.h"
#include "fuchsia_external_view_embedder.h"
#include "fuchsia_intl.h" #include "fuchsia_intl.h"
#include "platform_view.h" #include "platform_view.h"
#include "surface.h"
#include "task_runner_adapter.h" #include "task_runner_adapter.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "thread.h" #include "thread.h"
#if defined(LEGACY_FUCHSIA_EMBEDDER)
#include "compositor_context.h" // nogncheck
#endif
namespace flutter_runner { namespace flutter_runner {
namespace { namespace {
...@@ -65,6 +71,9 @@ Engine::Engine(Delegate& delegate, ...@@ -65,6 +71,9 @@ Engine::Engine(Delegate& delegate,
FlutterRunnerProductConfiguration product_config) FlutterRunnerProductConfiguration product_config)
: delegate_(delegate), : delegate_(delegate),
thread_label_(std::move(thread_label)), thread_label_(std::move(thread_label)),
#if defined(LEGACY_FUCHSIA_EMBEDDER)
use_legacy_renderer_(product_config.use_legacy_renderer()),
#endif
weak_factory_(this) { weak_factory_(this) {
if (zx::event::create(0, &vsync_event_) != ZX_OK) { if (zx::event::create(0, &vsync_event_) != ZX_OK) {
FML_DLOG(ERROR) << "Could not create the vsync event."; FML_DLOG(ERROR) << "Could not create the vsync event.";
...@@ -124,9 +133,18 @@ Engine::Engine(Delegate& delegate, ...@@ -124,9 +133,18 @@ Engine::Engine(Delegate& delegate,
thread_label_, std::move(session), thread_label_, std::move(session),
std::move(session_error_callback), [](auto) {}, vsync_handle); std::move(session_error_callback), [](auto) {}, vsync_handle);
surface_producer_.emplace(session_connection_->get()); surface_producer_.emplace(session_connection_->get());
scene_update_context_.emplace(thread_label_, std::move(view_token), #if defined(LEGACY_FUCHSIA_EMBEDDER)
std::move(view_ref_pair), if (use_legacy_renderer_) {
session_connection_.value()); legacy_external_view_embedder_.emplace(
thread_label_, std::move(view_token), std::move(view_ref_pair),
session_connection_.value());
} else
#endif
{
external_view_embedder_.emplace(
thread_label_, std::move(view_token), std::move(view_ref_pair),
session_connection_.value(), surface_producer_.value());
}
})); }));
// Grab the parent environment services. The platform view may want to // Grab the parent environment services. The platform view may want to
...@@ -152,11 +170,8 @@ Engine::Engine(Delegate& delegate, ...@@ -152,11 +170,8 @@ Engine::Engine(Delegate& delegate,
OnDestroyView on_destroy_view_callback = OnDestroyView on_destroy_view_callback =
std::bind(&Engine::DestroyView, this, std::placeholders::_1); std::bind(&Engine::DestroyView, this, std::placeholders::_1);
OnGetViewEmbedder on_get_view_embedder_callback = OnCreateSurface on_create_surface_callback =
std::bind(&Engine::GetViewEmbedder, this); std::bind(&Engine::CreateSurface, this);
OnGetGrContext on_get_gr_context_callback =
std::bind(&Engine::GetGrContext, this);
// SessionListener has a OnScenicError method; invoke this callback on the // SessionListener has a OnScenicError method; invoke this callback on the
// platform thread when that happens. The Session itself should also be // platform thread when that happens. The Session itself should also be
...@@ -187,11 +202,9 @@ Engine::Engine(Delegate& delegate, ...@@ -187,11 +202,9 @@ Engine::Engine(Delegate& delegate,
on_create_view_callback = std::move(on_create_view_callback), on_create_view_callback = std::move(on_create_view_callback),
on_update_view_callback = std::move(on_update_view_callback), on_update_view_callback = std::move(on_update_view_callback),
on_destroy_view_callback = std::move(on_destroy_view_callback), on_destroy_view_callback = std::move(on_destroy_view_callback),
on_get_view_embedder_callback = on_create_surface_callback = std::move(on_create_surface_callback),
std::move(on_get_view_embedder_callback), vsync_offset = product_config.get_vsync_offset(),
on_get_gr_context_callback = std::move(on_get_gr_context_callback), vsync_handle = vsync_event_.get()](flutter::Shell& shell) mutable {
vsync_handle = vsync_event_.get(),
product_config = product_config](flutter::Shell& shell) mutable {
return std::make_unique<flutter_runner::PlatformView>( return std::make_unique<flutter_runner::PlatformView>(
shell, // delegate shell, // delegate
debug_label, // debug label debug_label, // debug label
...@@ -206,27 +219,35 @@ Engine::Engine(Delegate& delegate, ...@@ -206,27 +219,35 @@ Engine::Engine(Delegate& delegate,
std::move(on_create_view_callback), std::move(on_create_view_callback),
std::move(on_update_view_callback), std::move(on_update_view_callback),
std::move(on_destroy_view_callback), std::move(on_destroy_view_callback),
std::move(on_get_view_embedder_callback), std::move(on_create_surface_callback),
std::move(on_get_gr_context_callback), std::move(vsync_offset), // vsync offset
vsync_handle, // vsync handle vsync_handle);
product_config);
}); });
// Setup the callback that will instantiate the rasterizer. // Setup the callback that will instantiate the rasterizer.
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer = flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer;
fml::MakeCopyable([this](flutter::Shell& shell) mutable { #if defined(LEGACY_FUCHSIA_EMBEDDER)
FML_DCHECK(session_connection_); on_create_rasterizer = [this](flutter::Shell& shell) {
FML_DCHECK(surface_producer_); if (use_legacy_renderer_) {
FML_DCHECK(scene_update_context_); FML_DCHECK(session_connection_);
FML_DCHECK(surface_producer_);
std::unique_ptr<flutter_runner::CompositorContext> compositor_context = FML_DCHECK(legacy_external_view_embedder_);
std::make_unique<flutter_runner::CompositorContext>(
session_connection_.value(), surface_producer_.value(), auto compositor_context =
scene_update_context_.value()); std::make_unique<flutter_runner::CompositorContext>(
session_connection_.value(), surface_producer_.value(),
return std::make_unique<flutter::Rasterizer>( legacy_external_view_embedder_.value());
shell, std::move(compositor_context)); return std::make_unique<flutter::Rasterizer>(
}); shell, std::move(compositor_context));
} else {
return std::make_unique<flutter::Rasterizer>(shell);
}
};
#else
on_create_rasterizer = [](flutter::Shell& shell) {
return std::make_unique<flutter::Rasterizer>(shell);
};
#endif
settings.root_isolate_create_callback = settings.root_isolate_create_callback =
std::bind(&Engine::OnMainIsolateStart, this); std::bind(&Engine::OnMainIsolateStart, this);
...@@ -479,59 +500,97 @@ void Engine::Terminate() { ...@@ -479,59 +500,97 @@ void Engine::Terminate() {
} }
void Engine::DebugWireframeSettingsChanged(bool enabled) { void Engine::DebugWireframeSettingsChanged(bool enabled) {
if (!shell_ || !scene_update_context_) { FML_CHECK(shell_);
return;
} shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask([this, enabled]() {
#if defined(LEGACY_FUCHSIA_EMBEDDER)
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask( if (use_legacy_renderer_) {
[this, enabled]() { scene_update_context_->EnableWireframe(enabled); }); FML_CHECK(legacy_external_view_embedder_);
legacy_external_view_embedder_->EnableWireframe(enabled);
} else
#endif
{
FML_CHECK(external_view_embedder_);
external_view_embedder_->EnableWireframe(enabled);
}
});
} }
void Engine::CreateView(int64_t view_id, bool hit_testable, bool focusable) { void Engine::CreateView(int64_t view_id, bool hit_testable, bool focusable) {
if (!shell_ || !scene_update_context_) { FML_CHECK(shell_);
return;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask( shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[this, view_id, hit_testable, focusable]() { [this, view_id, hit_testable, focusable]() {
scene_update_context_->CreateView(view_id, hit_testable, focusable); #if defined(LEGACY_FUCHSIA_EMBEDDER)
if (use_legacy_renderer_) {
FML_CHECK(legacy_external_view_embedder_);
legacy_external_view_embedder_->CreateView(view_id, hit_testable,
focusable);
} else
#endif
{
FML_CHECK(external_view_embedder_);
external_view_embedder_->CreateView(view_id);
external_view_embedder_->SetViewProperties(view_id, hit_testable,
focusable);
}
}); });
} }
void Engine::UpdateView(int64_t view_id, bool hit_testable, bool focusable) { void Engine::UpdateView(int64_t view_id, bool hit_testable, bool focusable) {
if (!shell_ || !scene_update_context_) { FML_CHECK(shell_);
return;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask( shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[this, view_id, hit_testable, focusable]() { [this, view_id, hit_testable, focusable]() {
scene_update_context_->UpdateView(view_id, hit_testable, focusable); #if defined(LEGACY_FUCHSIA_EMBEDDER)
if (use_legacy_renderer_) {
FML_CHECK(legacy_external_view_embedder_);
legacy_external_view_embedder_->UpdateView(view_id, hit_testable,
focusable);
} else
#endif
{
FML_CHECK(external_view_embedder_);
external_view_embedder_->SetViewProperties(view_id, hit_testable,
focusable);
}
}); });
} }
void Engine::DestroyView(int64_t view_id) { void Engine::DestroyView(int64_t view_id) {
if (!shell_ || !scene_update_context_) { FML_CHECK(shell_);
return;
} shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask([this, view_id]() {
#if defined(LEGACY_FUCHSIA_EMBEDDER)
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask( if (use_legacy_renderer_) {
[this, view_id]() { scene_update_context_->DestroyView(view_id); }); FML_CHECK(legacy_external_view_embedder_);
legacy_external_view_embedder_->DestroyView(view_id);
} else
#endif
{
FML_CHECK(external_view_embedder_);
external_view_embedder_->DestroyView(view_id);
}
});
} }
flutter::ExternalViewEmbedder* Engine::GetViewEmbedder() { std::unique_ptr<flutter::Surface> Engine::CreateSurface() {
if (!scene_update_context_) { flutter::ExternalViewEmbedder* external_view_embedder = nullptr;
return nullptr;
}
return &scene_update_context_.value();
}
GrDirectContext* Engine::GetGrContext() { #if defined(LEGACY_FUCHSIA_EMBEDDER)
// GetGrContext should be called only after rasterizer is created. if (use_legacy_renderer_) {
FML_DCHECK(shell_); FML_CHECK(legacy_external_view_embedder_);
FML_DCHECK(shell_->GetRasterizer()); external_view_embedder = &legacy_external_view_embedder_.value();
} else
#endif
{
FML_CHECK(external_view_embedder_);
external_view_embedder = &external_view_embedder_.value();
}
FML_CHECK(external_view_embedder);
return surface_producer_->gr_context(); return std::make_unique<Surface>(thread_label_, external_view_embedder,
surface_producer_->gr_context());
} }
#if !defined(DART_PRODUCT) #if !defined(DART_PRODUCT)
......
...@@ -14,17 +14,21 @@ ...@@ -14,17 +14,21 @@
#include <lib/ui/scenic/cpp/view_ref_pair.h> #include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <lib/zx/event.h> #include <lib/zx/event.h>
#include "flutter/flow/embedded_views.h" #include "flutter/flow/surface.h"
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h" #include "flutter/fml/macros.h"
#include "flutter/shell/common/shell.h" #include "flutter/shell/common/shell.h"
#include "flutter_runner_product_configuration.h" #include "flutter_runner_product_configuration.h"
#include "fuchsia_external_view_embedder.h"
#include "isolate_configurator.h" #include "isolate_configurator.h"
#include "session_connection.h" #include "session_connection.h"
#include "thread.h" #include "thread.h"
#include "vulkan_surface_producer.h" #include "vulkan_surface_producer.h"
#if defined(LEGACY_FUCHSIA_EMBEDDER)
#include "flutter/flow/scene_update_context.h" // nogncheck
#endif
namespace flutter_runner { namespace flutter_runner {
// Represents an instance of running Flutter engine along with the threads // Represents an instance of running Flutter engine along with the threads
...@@ -65,7 +69,10 @@ class Engine final { ...@@ -65,7 +69,10 @@ class Engine final {
std::optional<SessionConnection> session_connection_; std::optional<SessionConnection> session_connection_;
std::optional<VulkanSurfaceProducer> surface_producer_; std::optional<VulkanSurfaceProducer> surface_producer_;
std::optional<flutter::SceneUpdateContext> scene_update_context_; std::optional<FuchsiaExternalViewEmbedder> external_view_embedder_;
#if defined(LEGACY_FUCHSIA_EMBEDDER)
std::optional<flutter::SceneUpdateContext> legacy_external_view_embedder_;
#endif
std::unique_ptr<IsolateConfigurator> isolate_configurator_; std::unique_ptr<IsolateConfigurator> isolate_configurator_;
std::unique_ptr<flutter::Shell> shell_; std::unique_ptr<flutter::Shell> shell_;
...@@ -74,6 +81,10 @@ class Engine final { ...@@ -74,6 +81,10 @@ class Engine final {
zx::event vsync_event_; zx::event vsync_event_;
#if defined(LEGACY_FUCHSIA_EMBEDDER)
bool use_legacy_renderer_ = true;
#endif
fml::WeakPtrFactory<Engine> weak_factory_; fml::WeakPtrFactory<Engine> weak_factory_;
void OnMainIsolateStart(); void OnMainIsolateStart();
...@@ -87,9 +98,7 @@ class Engine final { ...@@ -87,9 +98,7 @@ class Engine final {
void UpdateView(int64_t view_id, bool hit_testable, bool focusable); void UpdateView(int64_t view_id, bool hit_testable, bool focusable);
void DestroyView(int64_t view_id); void DestroyView(int64_t view_id);
flutter::ExternalViewEmbedder* GetViewEmbedder(); std::unique_ptr<flutter::Surface> CreateSurface();
GrDirectContext* GetGrContext();
FML_DISALLOW_COPY_AND_ASSIGN(Engine); FML_DISALLOW_COPY_AND_ASSIGN(Engine);
}; };
......
...@@ -20,6 +20,11 @@ FlutterRunnerProductConfiguration::FlutterRunnerProductConfiguration( ...@@ -20,6 +20,11 @@ FlutterRunnerProductConfiguration::FlutterRunnerProductConfiguration(
if (auto& val = document["vsync_offset_in_us"]; val.IsInt()) { if (auto& val = document["vsync_offset_in_us"]; val.IsInt()) {
vsync_offset_ = fml::TimeDelta::FromMicroseconds(val.GetInt()); vsync_offset_ = fml::TimeDelta::FromMicroseconds(val.GetInt());
} }
#if defined(LEGACY_FUCHSIA_EMBEDDER)
if (auto& val = document["use_legacy_renderer"]; val.IsBool()) {
use_legacy_renderer_ = val.GetBool();
}
#endif
} }
} // namespace flutter_runner } // namespace flutter_runner
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_RUNNER_PRODUCT_CONFIGURATION_H_ #ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_RUNNER_PRODUCT_CONFIGURATION_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_RUNNER_PRODUCT_CONFIGURATION_H_ #define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_RUNNER_PRODUCT_CONFIGURATION_H_
#include "flutter/fml/time/time_delta.h" #include "flutter/fml/time/time_delta.h"
namespace flutter_runner { namespace flutter_runner {
...@@ -14,9 +15,15 @@ class FlutterRunnerProductConfiguration { ...@@ -14,9 +15,15 @@ class FlutterRunnerProductConfiguration {
FlutterRunnerProductConfiguration(std::string path); FlutterRunnerProductConfiguration(std::string path);
fml::TimeDelta get_vsync_offset() { return vsync_offset_; } fml::TimeDelta get_vsync_offset() { return vsync_offset_; }
#if defined(LEGACY_FUCHSIA_EMBEDDER)
bool use_legacy_renderer() { return use_legacy_renderer_; }
#endif
private: private:
fml::TimeDelta vsync_offset_ = fml::TimeDelta::Zero(); fml::TimeDelta vsync_offset_ = fml::TimeDelta::Zero();
#if defined(LEGACY_FUCHSIA_EMBEDDER)
bool use_legacy_renderer_ = true;
#endif
}; };
} // namespace flutter_runner } // namespace flutter_runner
......
// 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 "fuchsia_external_view_embedder.h"
#include <lib/ui/scenic/cpp/commands.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <zircon/types.h>
#include <algorithm> // For std::clamp
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace flutter_runner {
namespace {
// Layer separation is as infinitesimal as possible without introducing
// Z-fighting.
constexpr float kScenicZElevationBetweenLayers = 0.0001f;
constexpr float kScenicZElevationForPlatformView = 100.f;
} // namespace
FuchsiaExternalViewEmbedder::FuchsiaExternalViewEmbedder(
std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
SessionConnection& session,
VulkanSurfaceProducer& surface_producer)
: session_(session),
surface_producer_(surface_producer),
root_view_(session_.get(),
std::move(view_token),
std::move(view_ref_pair.control_ref),
std::move(view_ref_pair.view_ref),
debug_label),
metrics_node_(session_.get()),
root_node_(session_.get()) {
root_view_.AddChild(metrics_node_);
metrics_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
metrics_node_.SetLabel("Flutter::MetricsWatcher");
metrics_node_.AddChild(root_node_);
root_node_.SetLabel("Flutter::LayerTree");
session_.Present();
}
FuchsiaExternalViewEmbedder::~FuchsiaExternalViewEmbedder() = default;
SkCanvas* FuchsiaExternalViewEmbedder::GetRootCanvas() {
auto found = frame_layers_.find(kRootLayerId);
if (found == frame_layers_.end()) {
FML_DLOG(WARNING)
<< "No root canvas could be found. This is extremely unlikely and "
"indicates that the external view embedder did not receive the "
"notification to begin the frame.";
return nullptr;
}
return found->second.canvas_spy->GetSpyingCanvas();
}
std::vector<SkCanvas*> FuchsiaExternalViewEmbedder::GetCurrentCanvases() {
std::vector<SkCanvas*> canvases;
for (const auto& layer : frame_layers_) {
// This method (for legacy reasons) expects non-root current canvases.
if (layer.first.has_value()) {
canvases.push_back(layer.second.canvas_spy->GetSpyingCanvas());
}
}
return canvases;
}
void FuchsiaExternalViewEmbedder::PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<flutter::EmbeddedViewParams> params) {
zx_handle_t handle = static_cast<zx_handle_t>(view_id);
FML_DCHECK(frame_layers_.count(handle) == 0);
frame_layers_.emplace(std::make_pair(EmbedderLayerId{handle},
EmbedderLayer(frame_size_, *params)));
frame_composition_order_.push_back(handle);
}
SkCanvas* FuchsiaExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
zx_handle_t handle = static_cast<zx_handle_t>(view_id);
auto found = frame_layers_.find(handle);
FML_DCHECK(found != frame_layers_.end());
return found->second.canvas_spy->GetSpyingCanvas();
}
flutter::PostPrerollResult FuchsiaExternalViewEmbedder::PostPrerollAction(
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
return flutter::PostPrerollResult::kSuccess;
}
void FuchsiaExternalViewEmbedder::BeginFrame(
SkISize frame_size,
GrDirectContext* context,
double device_pixel_ratio,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
TRACE_EVENT0("flutter", "FuchsiaExternalViewEmbedder::BeginFrame");
// Reset for new frame.
Reset();
frame_size_ = frame_size;
frame_dpr_ = device_pixel_ratio;
// Create the root layer.
frame_layers_.emplace(
std::make_pair(kRootLayerId, EmbedderLayer(frame_size, std::nullopt)));
frame_composition_order_.push_back(kRootLayerId);
}
void FuchsiaExternalViewEmbedder::EndFrame(
bool should_resubmit_frame,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
TRACE_EVENT0("flutter", "FuchsiaExternalViewEmbedder::EndFrame");
}
void FuchsiaExternalViewEmbedder::SubmitFrame(
GrDirectContext* context,
std::unique_ptr<flutter::SurfaceFrame> frame) {
TRACE_EVENT0("flutter", "FuchsiaExternalViewEmbedder::SubmitFrame");
std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
std::unordered_map<EmbedderLayerId, size_t> frame_surface_indices;
// Create surfaces for the frame and associate them with layer IDs.
{
TRACE_EVENT0("flutter", "CreateSurfaces");
for (const auto& layer : frame_layers_) {
if (!layer.second.canvas_spy->DidDrawIntoCanvas()) {
continue;
}
auto surface =
surface_producer_.ProduceSurface(layer.second.surface_size);
FML_DCHECK(surface)
<< "Embedder did not return a valid render target of size ("
<< layer.second.surface_size.width() << ", "
<< layer.second.surface_size.height() << ")";
frame_surface_indices.emplace(
std::make_pair(layer.first, frame_surfaces.size()));
frame_surfaces.emplace_back(std::move(surface));
}
}
// Submit layers and platform views to Scenic in composition order.
{
TRACE_EVENT0("flutter", "SubmitLayers");
std::unordered_map<uint64_t, size_t> scenic_rect_indices;
size_t scenic_layer_index = 0;
float embedded_views_height = 0.0f;
// First re-scale everything according to the DPR.
const float inv_dpr = 1.0f / frame_dpr_;
root_node_.SetScale(inv_dpr, inv_dpr, 1.0f);
for (const auto& layer_id : frame_composition_order_) {
const auto& layer = frame_layers_.find(layer_id);
FML_DCHECK(layer != frame_layers_.end());
// Draw the PlatformView associated with each layer first.
if (layer_id.has_value()) {
FML_DCHECK(layer->second.embedded_view_params.has_value());
auto& view_params = layer->second.embedded_view_params.value();
// Compute offset and size for the platform view.
SkPoint view_offset =
SkPoint::Make(view_params.finalBoundingRect().left(),
view_params.finalBoundingRect().top());
SkSize view_size =
SkSize::Make(view_params.finalBoundingRect().width(),
view_params.finalBoundingRect().height());
// Compute opacity for the platform view.
float view_opacity = 1.0f;
for (auto i = view_params.mutatorsStack().Bottom();
i != view_params.mutatorsStack().Top(); ++i) {
const auto& mutator = *i;
switch (mutator->GetType()) {
case flutter::MutatorType::opacity: {
view_opacity *= std::clamp(mutator->GetAlphaFloat(), 0.0f, 1.0f);
} break;
default: {
break;
}
}
}
auto found = scenic_views_.find(layer_id.value());
FML_DCHECK(found != scenic_views_.end());
auto& view_holder = found->second;
// Set opacity.
if (view_opacity != view_holder.opacity) {
view_holder.opacity_node.SetOpacity(view_opacity);
view_holder.opacity = view_opacity;
}
// Set offset and elevation.
const float view_elevation =
kScenicZElevationBetweenLayers * scenic_layer_index +
embedded_views_height;
if (view_offset != view_holder.offset ||
view_elevation != view_holder.elevation) {
view_holder.entity_node.SetTranslation(view_offset.fX, view_offset.fY,
-view_elevation);
view_holder.elevation = view_elevation;
}
// Set HitTestBehavior.
if (view_holder.pending_hit_testable != view_holder.hit_testable) {
view_holder.entity_node.SetHitTestBehavior(
view_holder.pending_hit_testable
? fuchsia::ui::gfx::HitTestBehavior::kDefault
: fuchsia::ui::gfx::HitTestBehavior::kSuppress);
view_holder.hit_testable = view_holder.pending_hit_testable;
}
// Set size and focusable.
//
// Scenic rejects `SetViewProperties` calls with a zero size.
if (!view_size.isEmpty() &&
(view_size != view_holder.size ||
view_holder.pending_focusable != view_holder.focusable)) {
view_holder.view_holder.SetViewProperties({
.bounding_box =
{
.min = {.x = 0.f, .y = 0.f, .z = -1000.f},
.max = {.x = view_size.width(),
.y = view_size.height(),
.z = 0.f},
},
.inset_from_min = {.x = 0.f, .y = 0.f, .z = 0.f},
.inset_from_max = {.x = 0.f, .y = 0.f, .z = 0.f},
.focus_change = view_holder.pending_focusable,
});
view_holder.size = view_size;
view_holder.focusable = view_holder.pending_focusable;
}
// Attach the ScenicView to the main scene graph.
root_node_.AddChild(view_holder.opacity_node);
// Account for the ScenicView's height when positioning the next layer.
embedded_views_height += kScenicZElevationForPlatformView;
}
if (layer->second.canvas_spy->DidDrawIntoCanvas()) {
const auto& surface_index = frame_surface_indices.find(layer_id);
FML_DCHECK(surface_index != frame_surface_indices.end());
scenic::Image* surface_image =
frame_surfaces[surface_index->second]->GetImage();
// Create a new layer if needed for the surface.
FML_DCHECK(scenic_layer_index <= scenic_layers_.size());
if (scenic_layer_index == scenic_layers_.size()) {
ScenicLayer new_layer{
.shape_node = scenic::ShapeNode(session_.get()),
.material = scenic::Material(session_.get()),
};
new_layer.shape_node.SetMaterial(new_layer.material);
scenic_layers_.emplace_back(std::move(new_layer));
}
// Compute a hash and index for the rect.
const uint64_t rect_hash =
(static_cast<uint64_t>(layer->second.surface_size.width()) << 32) +
layer->second.surface_size.height();
size_t rect_index = 0;
auto found_index = scenic_rect_indices.find(rect_hash);
if (found_index == scenic_rect_indices.end()) {
scenic_rect_indices.emplace(std::make_pair(rect_hash, 0));
} else {
rect_index = found_index->second + 1;
scenic_rect_indices[rect_hash] = rect_index;
}
// Create a new rect if needed for the surface.
auto found_rects = scenic_rects_.find(rect_hash);
if (found_rects == scenic_rects_.end()) {
auto [emplaced_rects, success] = scenic_rects_.emplace(
std::make_pair(rect_hash, std::vector<scenic::Rectangle>()));
FML_DCHECK(success);
found_rects = std::move(emplaced_rects);
}
FML_DCHECK(rect_index <= found_rects->second.size());
if (rect_index == found_rects->second.size()) {
found_rects->second.emplace_back(scenic::Rectangle(
session_.get(), layer->second.surface_size.width(),
layer->second.surface_size.height()));
}
// Set layer shape and texture.
// Scenic currently lacks an API to enable rendering of alpha channel;
// Flutter Embedder also lacks an API to detect if a layer has alpha or
// not. Alpha channels are only rendered if there is a OpacityNode
// higher in the tree with opacity != 1. For now, always assume t he
// layer has alpha and clamp to a infinitesimally smaller value than 1.
//
// This does not cause visual problems in practice, but probably has
// performance implications.
auto& scenic_layer = scenic_layers_[scenic_layer_index];
auto& scenic_rect = found_rects->second[rect_index];
const float layer_elevation =
kScenicZElevationBetweenLayers * scenic_layer_index +
embedded_views_height;
scenic_layer.shape_node.SetLabel("Flutter::Layer");
scenic_layer.shape_node.SetShape(scenic_rect);
scenic_layer.shape_node.SetTranslation(
layer->second.surface_size.width() * 0.5f,
layer->second.surface_size.height() * 0.5f, -layer_elevation);
scenic_layer.material.SetColor(SK_AlphaOPAQUE, SK_AlphaOPAQUE,
SK_AlphaOPAQUE, SK_AlphaOPAQUE - 1);
scenic_layer.material.SetTexture(*surface_image);
// Attach the ScenicLayer to the main scene graph.
root_node_.AddChild(scenic_layer.shape_node);
// Account for the ScenicLayer's height when positioning the next layer.
scenic_layer_index++;
}
}
}
// Present the session to Scenic, along with surface acquire/release fencess.
{
TRACE_EVENT0("flutter", "SessionPresent");
session_.Present();
}
// Render the recorded SkPictures into the surfaces.
{
TRACE_EVENT0("flutter", "RasterizeSurfaces");
for (const auto& surface_index : frame_surface_indices) {
TRACE_EVENT0("flutter", "RasterizeSurface");
const auto& layer = frame_layers_.find(surface_index.first);
FML_DCHECK(layer != frame_layers_.end());
sk_sp<SkPicture> picture =
layer->second.recorder->finishRecordingAsPicture();
FML_DCHECK(picture);
sk_sp<SkSurface> sk_surface =
frame_surfaces[surface_index.second]->GetSkiaSurface();
FML_DCHECK(sk_surface);
FML_DCHECK(SkISize::Make(sk_surface->width(), sk_surface->height()) ==
frame_size_);
SkCanvas* canvas = sk_surface->getCanvas();
FML_DCHECK(canvas);
canvas->setMatrix(SkMatrix::I());
canvas->clear(SK_ColorTRANSPARENT);
canvas->drawPicture(picture);
canvas->flush();
}
}
// Flush deferred Skia work and inform Scenic that render targets are ready.
{
TRACE_EVENT0("flutter", "PresentSurfaces");
surface_producer_.OnSurfacesPresented(std::move(frame_surfaces));
}
// Submit the underlying render-backend-specific frame for processing.
frame->Submit();
}
void FuchsiaExternalViewEmbedder::EnableWireframe(bool enable) {
session_.get()->Enqueue(
scenic::NewSetEnableDebugViewBoundsCmd(root_view_.id(), enable));
session_.Present();
}
void FuchsiaExternalViewEmbedder::CreateView(int64_t view_id) {
FML_DCHECK(scenic_views_.find(view_id) == scenic_views_.end());
ScenicView new_view = {
.opacity_node = scenic::OpacityNodeHACK(session_.get()),
.entity_node = scenic::EntityNode(session_.get()),
.view_holder = scenic::ViewHolder(
session_.get(),
scenic::ToViewHolderToken(zx::eventpair((zx_handle_t)view_id)),
"Flutter::PlatformView"),
};
new_view.opacity_node.SetLabel("flutter::PlatformView::OpacityMutator");
new_view.entity_node.SetLabel("flutter::PlatformView::TransformMutator");
new_view.opacity_node.AddChild(new_view.entity_node);
new_view.entity_node.Attach(new_view.view_holder);
new_view.entity_node.SetTranslation(0.f, 0.f,
-kScenicZElevationBetweenLayers);
scenic_views_.emplace(std::make_pair(view_id, std::move(new_view)));
}
void FuchsiaExternalViewEmbedder::DestroyView(int64_t view_id) {
size_t erased = scenic_views_.erase(view_id);
FML_DCHECK(erased == 1);
}
void FuchsiaExternalViewEmbedder::SetViewProperties(int64_t view_id,
bool hit_testable,
bool focusable) {
auto found = scenic_views_.find(view_id);
FML_DCHECK(found != scenic_views_.end());
auto& view_holder = found->second;
view_holder.pending_hit_testable = hit_testable;
view_holder.pending_focusable = focusable;
}
void FuchsiaExternalViewEmbedder::Reset() {
frame_layers_.clear();
frame_composition_order_.clear();
frame_size_ = SkISize::Make(0, 0);
frame_dpr_ = 1.f;
// Detach the root node to prepare for the next frame.
session_.get()->Enqueue(scenic::NewDetachChildrenCmd(root_node_.id()));
// Clear images on all layers so they aren't cached unnecesarily.
for (auto& layer : scenic_layers_) {
layer.material.SetTexture(0);
}
}
} // namespace flutter_runner
// 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_SHELL_PLATFORM_FUCHSIA_FLUTTER_FUCHSIA_EXTERNAL_VIEW_EMBEDDER_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FUCHSIA_EXTERNAL_VIEW_EMBEDDER_H_
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <cstdint> // For uint32_t & uint64_t
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/common/canvas_spy.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "session_connection.h"
#include "vulkan_surface_producer.h"
namespace flutter_runner {
// This class orchestrates interaction with the Scenic compositor on Fuchsia. It
// ensures that flutter content and platform view content are both rendered
// correctly in a unified scene.
class FuchsiaExternalViewEmbedder final : public flutter::ExternalViewEmbedder {
public:
FuchsiaExternalViewEmbedder(std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
SessionConnection& session,
VulkanSurfaceProducer& surface_producer);
~FuchsiaExternalViewEmbedder();
// |ExternalViewEmbedder|
SkCanvas* GetRootCanvas() override;
// |ExternalViewEmbedder|
std::vector<SkCanvas*> GetCurrentCanvases() override;
// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<flutter::EmbeddedViewParams> params) override;
// |ExternalViewEmbedder|
SkCanvas* CompositeEmbeddedView(int view_id) override;
// |ExternalViewEmbedder|
flutter::PostPrerollResult PostPrerollAction(
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override;
// |ExternalViewEmbedder|
void BeginFrame(
SkISize frame_size,
GrDirectContext* context,
double device_pixel_ratio,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override;
// |ExternalViewEmbedder|
void EndFrame(
bool should_resubmit_frame,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override;
// |ExternalViewEmbedder|
void SubmitFrame(GrDirectContext* context,
std::unique_ptr<flutter::SurfaceFrame> frame) override;
// |ExternalViewEmbedder|
void CancelFrame() override { Reset(); }
// |ExternalViewEmbedder|
bool SupportsDynamicThreadMerging() override { return false; }
// View manipulation.
// |SetViewProperties| doesn't manipulate the view directly -- it sets
// prending properties for the next |UpdateView| call.
void EnableWireframe(bool enable);
void CreateView(int64_t view_id);
void DestroyView(int64_t view_id);
void SetViewProperties(int64_t view_id, bool hit_testable, bool focusable);
private:
// Reset state for a new frame.
void Reset();
struct EmbedderLayer {
EmbedderLayer(const SkISize& frame_size,
std::optional<flutter::EmbeddedViewParams> view_params)
: embedded_view_params(std::move(view_params)),
recorder(std::make_unique<SkPictureRecorder>()),
canvas_spy(std::make_unique<flutter::CanvasSpy>(
recorder->beginRecording(frame_size.width(),
frame_size.height()))),
surface_size(frame_size) {}
std::optional<flutter::EmbeddedViewParams> embedded_view_params;
std::unique_ptr<SkPictureRecorder> recorder;
std::unique_ptr<flutter::CanvasSpy> canvas_spy;
SkISize surface_size;
};
struct ScenicView {
scenic::OpacityNodeHACK opacity_node;
scenic::EntityNode entity_node;
scenic::ViewHolder view_holder;
SkPoint offset = SkPoint::Make(0.f, 0.f);
SkSize size = SkSize::MakeEmpty();
float elevation = 0.f;
float opacity = 1.f;
bool hit_testable = false;
bool focusable = false;
bool pending_hit_testable = false;
bool pending_focusable = false;
};
struct ScenicLayer {
scenic::ShapeNode shape_node;
scenic::Material material;
};
using EmbedderLayerId = std::optional<uint32_t>;
constexpr static EmbedderLayerId kRootLayerId = EmbedderLayerId{};
SessionConnection& session_;
VulkanSurfaceProducer& surface_producer_;
scenic::View root_view_;
scenic::EntityNode metrics_node_;
scenic::EntityNode root_node_;
std::unordered_map<uint64_t, std::vector<scenic::Rectangle>> scenic_rects_;
std::unordered_map<int64_t, ScenicView> scenic_views_;
std::vector<ScenicLayer> scenic_layers_;
std::unordered_map<EmbedderLayerId, EmbedderLayer> frame_layers_;
std::vector<EmbedderLayerId> frame_composition_order_;
SkISize frame_size_ = SkISize::Make(0, 0);
float frame_dpr_ = 1.f;
FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaExternalViewEmbedder);
};
} // namespace flutter_runner
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FUCHSIA_EXTERNAL_VIEW_EMBEDDER_H_
...@@ -10,10 +10,8 @@ ...@@ -10,10 +10,8 @@
#include <sstream> #include <sstream>
#include "flutter/fml/logging.h" #include "flutter/fml/logging.h"
#include "flutter/lib/ui/compositing/scene_host.h"
#include "flutter/lib/ui/window/pointer_data.h" #include "flutter/lib/ui/window/pointer_data.h"
#include "flutter/lib/ui/window/window.h" #include "flutter/lib/ui/window/window.h"
#include "flutter_runner_product_configuration.h"
#include "logging.h" #include "logging.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
...@@ -21,6 +19,10 @@ ...@@ -21,6 +19,10 @@
#include "runtime/dart/utils/inlines.h" #include "runtime/dart/utils/inlines.h"
#include "vsync_waiter.h" #include "vsync_waiter.h"
#if defined(LEGACY_FUCHSIA_EMBEDDER)
#include "flutter/lib/ui/compositing/scene_host.h"
#endif
namespace flutter_runner { namespace flutter_runner {
static constexpr char kFlutterPlatformChannel[] = "flutter/platform"; static constexpr char kFlutterPlatformChannel[] = "flutter/platform";
...@@ -60,10 +62,9 @@ PlatformView::PlatformView( ...@@ -60,10 +62,9 @@ PlatformView::PlatformView(
OnCreateView on_create_view_callback, OnCreateView on_create_view_callback,
OnUpdateView on_update_view_callback, OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback, OnDestroyView on_destroy_view_callback,
OnGetViewEmbedder on_get_view_embedder_callback, OnCreateSurface on_create_surface_callback,
OnGetGrContext on_get_gr_context_callback, fml::TimeDelta vsync_offset,
zx_handle_t vsync_event_handle, zx_handle_t vsync_event_handle)
FlutterRunnerProductConfiguration product_config)
: flutter::PlatformView(delegate, std::move(task_runners)), : flutter::PlatformView(delegate, std::move(task_runners)),
debug_label_(std::move(debug_label)), debug_label_(std::move(debug_label)),
view_ref_(std::move(view_ref)), view_ref_(std::move(view_ref)),
...@@ -75,11 +76,10 @@ PlatformView::PlatformView( ...@@ -75,11 +76,10 @@ PlatformView::PlatformView(
on_create_view_callback_(std::move(on_create_view_callback)), on_create_view_callback_(std::move(on_create_view_callback)),
on_update_view_callback_(std::move(on_update_view_callback)), on_update_view_callback_(std::move(on_update_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)), on_destroy_view_callback_(std::move(on_destroy_view_callback)),
on_get_view_embedder_callback_(std::move(on_get_view_embedder_callback)), on_create_surface_callback_(std::move(on_create_surface_callback)),
on_get_gr_context_callback_(std::move(on_get_gr_context_callback)),
ime_client_(this), ime_client_(this),
vsync_event_handle_(vsync_event_handle), vsync_offset_(std::move(vsync_offset)),
product_config_(product_config) { vsync_event_handle_(vsync_event_handle) {
// Register all error handlers. // Register all error handlers.
SetInterfaceErrorHandler(session_listener_binding_, "SessionListener"); SetInterfaceErrorHandler(session_listener_binding_, "SessionListener");
SetInterfaceErrorHandler(ime_, "Input Method Editor"); SetInterfaceErrorHandler(ime_, "Input Method Editor");
...@@ -248,6 +248,7 @@ void PlatformView::OnScenicEvent( ...@@ -248,6 +248,7 @@ void PlatformView::OnScenicEvent(
} }
break; break;
} }
#if defined(LEGACY_FUCHSIA_EMBEDDER)
case fuchsia::ui::gfx::Event::Tag::kViewConnected: case fuchsia::ui::gfx::Event::Tag::kViewConnected:
OnChildViewConnected(event.gfx().view_connected().view_holder_id); OnChildViewConnected(event.gfx().view_connected().view_holder_id);
break; break;
...@@ -260,6 +261,7 @@ void PlatformView::OnScenicEvent( ...@@ -260,6 +261,7 @@ void PlatformView::OnScenicEvent(
event.gfx().view_state_changed().view_holder_id, event.gfx().view_state_changed().view_holder_id,
event.gfx().view_state_changed().state.is_rendering); event.gfx().view_state_changed().state.is_rendering);
break; break;
#endif
case fuchsia::ui::gfx::Event::Tag::Invalid: case fuchsia::ui::gfx::Event::Tag::Invalid:
FML_DCHECK(false) << "Flutter PlatformView::OnScenicEvent: Got " FML_DCHECK(false) << "Flutter PlatformView::OnScenicEvent: Got "
"an invalid GFX event."; "an invalid GFX event.";
...@@ -317,6 +319,7 @@ void PlatformView::OnScenicEvent( ...@@ -317,6 +319,7 @@ void PlatformView::OnScenicEvent(
} }
} }
#if defined(LEGACY_FUCHSIA_EMBEDDER)
void PlatformView::OnChildViewConnected(scenic::ResourceId view_holder_id) { void PlatformView::OnChildViewConnected(scenic::ResourceId view_holder_id) {
task_runners_.GetUITaskRunner()->PostTask([view_holder_id]() { task_runners_.GetUITaskRunner()->PostTask([view_holder_id]() {
flutter::SceneHost::OnViewConnected(view_holder_id); flutter::SceneHost::OnViewConnected(view_holder_id);
...@@ -335,6 +338,7 @@ void PlatformView::OnChildViewStateChanged(scenic::ResourceId view_holder_id, ...@@ -335,6 +338,7 @@ void PlatformView::OnChildViewStateChanged(scenic::ResourceId view_holder_id,
flutter::SceneHost::OnViewStateChanged(view_holder_id, state); flutter::SceneHost::OnViewStateChanged(view_holder_id, state);
}); });
} }
#endif
static flutter::PointerData::Change GetChangeFromPointerEventPhase( static flutter::PointerData::Change GetChangeFromPointerEventPhase(
fuchsia::ui::input::PointerEventPhase phase) { fuchsia::ui::input::PointerEventPhase phase) {
...@@ -513,21 +517,12 @@ void PlatformView::DeactivateIme() { ...@@ -513,21 +517,12 @@ void PlatformView::DeactivateIme() {
// |flutter::PlatformView| // |flutter::PlatformView|
std::unique_ptr<flutter::VsyncWaiter> PlatformView::CreateVSyncWaiter() { std::unique_ptr<flutter::VsyncWaiter> PlatformView::CreateVSyncWaiter() {
return std::make_unique<flutter_runner::VsyncWaiter>( return std::make_unique<flutter_runner::VsyncWaiter>(
debug_label_, vsync_event_handle_, task_runners_, debug_label_, vsync_event_handle_, task_runners_, vsync_offset_);
product_config_.get_vsync_offset());
} }
// |flutter::PlatformView| // |flutter::PlatformView|
std::unique_ptr<flutter::Surface> PlatformView::CreateRenderingSurface() { std::unique_ptr<flutter::Surface> PlatformView::CreateRenderingSurface() {
// This platform does not repeatly lose and gain a surface connection. So the return on_create_surface_callback_ ? on_create_surface_callback_() : nullptr;
// surface is setup once during platform view setup and returned to the
// shell on the initial (and only) |NotifyCreated| call.
auto view_embedder = on_get_view_embedder_callback_
? on_get_view_embedder_callback_()
: nullptr;
auto gr_context =
on_get_gr_context_callback_ ? on_get_gr_context_callback_() : nullptr;
return std::make_unique<Surface>(debug_label_, view_embedder, gr_context);
} }
// |flutter::PlatformView| // |flutter::PlatformView|
......
...@@ -7,18 +7,21 @@ ...@@ -7,18 +7,21 @@
#include <fuchsia/ui/input/cpp/fidl.h> #include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h> #include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fit/function.h> #include <lib/fit/function.h>
#include <map> #include <map>
#include <set> #include <set>
#include "flutter/fml/macros.h" #include "flutter/fml/macros.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/shell/common/platform_view.h" #include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/fuchsia/flutter/accessibility_bridge.h"
#include "flutter_runner_product_configuration.h" #include "accessibility_bridge.h"
#include "lib/fidl/cpp/binding.h"
#include "lib/ui/scenic/cpp/id.h" #if defined(LEGACY_FUCHSIA_EMBEDDER)
#include "surface.h" #include <lib/ui/scenic/cpp/id.h> // nogncheck
#endif
namespace flutter_runner { namespace flutter_runner {
...@@ -26,8 +29,7 @@ using OnEnableWireframe = fit::function<void(bool)>; ...@@ -26,8 +29,7 @@ using OnEnableWireframe = fit::function<void(bool)>;
using OnCreateView = fit::function<void(int64_t, bool, bool)>; using OnCreateView = fit::function<void(int64_t, bool, bool)>;
using OnUpdateView = fit::function<void(int64_t, bool, bool)>; using OnUpdateView = fit::function<void(int64_t, bool, bool)>;
using OnDestroyView = fit::function<void(int64_t)>; using OnDestroyView = fit::function<void(int64_t)>;
using OnGetViewEmbedder = fit::function<flutter::ExternalViewEmbedder*()>; using OnCreateSurface = fit::function<std::unique_ptr<flutter::Surface>()>;
using OnGetGrContext = fit::function<GrDirectContext*()>;
// The per engine component residing on the platform thread is responsible for // The per engine component residing on the platform thread is responsible for
// all platform specific integrations. // all platform specific integrations.
...@@ -55,10 +57,9 @@ class PlatformView final : public flutter::PlatformView, ...@@ -55,10 +57,9 @@ class PlatformView final : public flutter::PlatformView,
OnCreateView on_create_view_callback, OnCreateView on_create_view_callback,
OnUpdateView on_update_view_callback, OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback, OnDestroyView on_destroy_view_callback,
OnGetViewEmbedder on_get_view_embedder_callback, OnCreateSurface on_create_surface_callback,
OnGetGrContext on_get_gr_context_callback, fml::TimeDelta vsync_offset,
zx_handle_t vsync_event_handle, zx_handle_t vsync_event_handle);
FlutterRunnerProductConfiguration product_config);
~PlatformView(); ~PlatformView();
...@@ -87,8 +88,7 @@ class PlatformView final : public flutter::PlatformView, ...@@ -87,8 +88,7 @@ class PlatformView final : public flutter::PlatformView,
OnCreateView on_create_view_callback_; OnCreateView on_create_view_callback_;
OnUpdateView on_update_view_callback_; OnUpdateView on_update_view_callback_;
OnDestroyView on_destroy_view_callback_; OnDestroyView on_destroy_view_callback_;
OnGetViewEmbedder on_get_view_embedder_callback_; OnCreateSurface on_create_surface_callback_;
OnGetGrContext on_get_gr_context_callback_;
int current_text_input_client_ = 0; int current_text_input_client_ = 0;
fidl::Binding<fuchsia::ui::input::InputMethodEditorClient> ime_client_; fidl::Binding<fuchsia::ui::input::InputMethodEditorClient> ime_client_;
...@@ -112,14 +112,14 @@ class PlatformView final : public flutter::PlatformView, ...@@ -112,14 +112,14 @@ class PlatformView final : public flutter::PlatformView,
// such. Notifying via logs multiple times results in log-spam. See: // such. Notifying via logs multiple times results in log-spam. See:
// https://github.com/flutter/flutter/issues/55966 // https://github.com/flutter/flutter/issues/55966
std::set<std::string /* channel */> unregistered_channels_; std::set<std::string /* channel */> unregistered_channels_;
fml::TimeDelta vsync_offset_;
zx_handle_t vsync_event_handle_ = 0; zx_handle_t vsync_event_handle_ = 0;
float view_width_ = 0.0f; // Width in logical pixels. float view_width_ = 0.0f; // Width in logical pixels.
float view_height_ = 0.0f; // Height in logical pixels. float view_height_ = 0.0f; // Height in logical pixels.
float view_pixel_ratio_ = 0.0f; // Logical / physical pixel ratio. float view_pixel_ratio_ = 0.0f; // Logical / physical pixel ratio.
FlutterRunnerProductConfiguration product_config_;
void RegisterPlatformMessageHandlers(); void RegisterPlatformMessageHandlers();
// |fuchsia::ui::input::InputMethodEditorClient| // |fuchsia::ui::input::InputMethodEditorClient|
...@@ -134,9 +134,11 @@ class PlatformView final : public flutter::PlatformView, ...@@ -134,9 +134,11 @@ class PlatformView final : public flutter::PlatformView,
void OnScenicError(std::string error) override; void OnScenicError(std::string error) override;
void OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) override; void OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) override;
#if defined(LEGACY_FUCHSIA_EMBEDDER)
void OnChildViewConnected(scenic::ResourceId view_holder_id); void OnChildViewConnected(scenic::ResourceId view_holder_id);
void OnChildViewDisconnected(scenic::ResourceId view_holder_id); void OnChildViewDisconnected(scenic::ResourceId view_holder_id);
void OnChildViewStateChanged(scenic::ResourceId view_holder_id, bool state); void OnChildViewStateChanged(scenic::ResourceId view_holder_id, bool state);
#endif
bool OnHandlePointerEvent(const fuchsia::ui::input::PointerEvent& pointer); bool OnHandlePointerEvent(const fuchsia::ui::input::PointerEvent& pointer);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "flutter/lib/ui/window/window.h" #include "flutter/lib/ui/window/window.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "surface.h"
#include "task_runner_adapter.h" #include "task_runner_adapter.h"
namespace flutter_runner_test::flutter_runner_a11y_test { namespace flutter_runner_test::flutter_runner_a11y_test {
...@@ -116,10 +117,7 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate { ...@@ -116,10 +117,7 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
bool SemanticsEnabled() const { return semantics_enabled_; } bool SemanticsEnabled() const { return semantics_enabled_; }
int32_t SemanticsFeatures() const { return semantics_features_; } int32_t SemanticsFeatures() const { return semantics_features_; }
flutter::ExternalViewEmbedder* get_view_embedder() { flutter::Surface* surface() const { return surface_.get(); }
return surface_->GetExternalViewEmbedder();
}
GrDirectContext* get_gr_context() { return surface_->GetContext(); }
private: private:
std::unique_ptr<flutter::Surface> surface_; std::unique_ptr<flutter::Surface> surface_;
...@@ -162,18 +160,17 @@ TEST_F(PlatformViewTests, ChangesAccessibilitySettings) { ...@@ -162,18 +160,17 @@ TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
std::move(view_ref), // view_ref std::move(view_ref), // view_ref
std::move(task_runners), // task_runners std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request nullptr, // session_listener_request
nullptr, // focuser, nullptr, // focuser,
nullptr, // on_session_listener_error_callback nullptr, // on_session_listener_error_callback
nullptr, // on_enable_wireframe_callback, nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback, nullptr, // on_create_view_callback,
nullptr, // on_update_view_callback, nullptr, // on_update_view_callback,
nullptr, // on_destroy_view_callback, nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback, nullptr, // on_create_surface_callback,
nullptr, // on_get_gr_context_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
RunLoopUntilIdle(); RunLoopUntilIdle();
...@@ -227,10 +224,9 @@ TEST_F(PlatformViewTests, EnableWireframeTest) { ...@@ -227,10 +224,9 @@ TEST_F(PlatformViewTests, EnableWireframeTest) {
nullptr, // on_create_view_callback, nullptr, // on_create_view_callback,
nullptr, // on_update_view_callback, nullptr, // on_update_view_callback,
nullptr, // on_destroy_view_callback, nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback, nullptr, // on_create_surface_callback,
nullptr, // on_get_gr_context_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
// Cast platform_view to its base view so we can have access to the public // Cast platform_view to its base view so we can have access to the public
...@@ -287,18 +283,17 @@ TEST_F(PlatformViewTests, CreateViewTest) { ...@@ -287,18 +283,17 @@ TEST_F(PlatformViewTests, CreateViewTest) {
std::move(view_ref), // view_refs std::move(view_ref), // view_refs
std::move(task_runners), // task_runners std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request nullptr, // session_listener_request
nullptr, // focuser, nullptr, // focuser,
nullptr, // on_session_listener_error_callback nullptr, // on_session_listener_error_callback
nullptr, // on_enable_wireframe_callback, nullptr, // on_enable_wireframe_callback,
CreateViewCallback, // on_create_view_callback, CreateViewCallback, // on_create_view_callback,
nullptr, // on_update_view_callback, nullptr, // on_update_view_callback,
nullptr, // on_destroy_view_callback, nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback, nullptr, // on_create_surface_callback,
nullptr, // on_get_gr_context_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
// Cast platform_view to its base view so we can have access to the public // Cast platform_view to its base view so we can have access to the public
...@@ -357,18 +352,17 @@ TEST_F(PlatformViewTests, UpdateViewTest) { ...@@ -357,18 +352,17 @@ TEST_F(PlatformViewTests, UpdateViewTest) {
std::move(view_ref), // view_refs std::move(view_ref), // view_refs
std::move(task_runners), // task_runners std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request nullptr, // session_listener_request
nullptr, // focuser, nullptr, // focuser,
nullptr, // on_session_listener_error_callback nullptr, // on_session_listener_error_callback
nullptr, // on_enable_wireframe_callback, nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback, nullptr, // on_create_view_callback,
UpdateViewCallback, // on_update_view_callback, UpdateViewCallback, // on_update_view_callback,
nullptr, // on_destroy_view_callback, nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback, nullptr, // on_create_surface_callback,
nullptr, // on_get_gr_context_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
// Cast platform_view to its base view so we can have access to the public // Cast platform_view to its base view so we can have access to the public
...@@ -427,18 +421,17 @@ TEST_F(PlatformViewTests, DestroyViewTest) { ...@@ -427,18 +421,17 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
std::move(view_ref), // view_refs std::move(view_ref), // view_refs
std::move(task_runners), // task_runners std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request nullptr, // session_listener_request
nullptr, // focuser, nullptr, // focuser,
nullptr, // on_session_listener_error_callback nullptr, // on_session_listener_error_callback
nullptr, // on_enable_wireframe_callback, nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback, nullptr, // on_create_view_callback,
nullptr, // on_update_view_callback, nullptr, // on_update_view_callback,
DestroyViewCallback, // on_destroy_view_callback, DestroyViewCallback, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback, nullptr, // on_create_surface_callback,
nullptr, // on_get_gr_context_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
// Cast platform_view to its base view so we can have access to the public // Cast platform_view to its base view so we can have access to the public
...@@ -499,10 +492,9 @@ TEST_F(PlatformViewTests, RequestFocusTest) { ...@@ -499,10 +492,9 @@ TEST_F(PlatformViewTests, RequestFocusTest) {
nullptr, // on_create_view_callback, nullptr, // on_create_view_callback,
nullptr, // on_update_view_callback, nullptr, // on_update_view_callback,
nullptr, // on_destroy_view_callback, nullptr, // on_destroy_view_callback,
nullptr, // on_get_gr_context_callback, nullptr, // on_create_surface_callback,
nullptr, // on_get_view_embedder_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
// Cast platform_view to its base view so we can have access to the public // Cast platform_view to its base view so we can have access to the public
...@@ -534,8 +526,8 @@ TEST_F(PlatformViewTests, RequestFocusTest) { ...@@ -534,8 +526,8 @@ TEST_F(PlatformViewTests, RequestFocusTest) {
} }
// Test to make sure that PlatformView correctly returns a Surface instance // Test to make sure that PlatformView correctly returns a Surface instance
// that can surface the view_embedder provided from GetViewEmbedderCallback. // that can surface the provided gr_context and view_embedder.
TEST_F(PlatformViewTests, GetViewEmbedderTest) { TEST_F(PlatformViewTests, CreateSurfaceTest) {
sys::testing::ServiceDirectoryProvider services_provider(dispatcher()); sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
MockPlatformViewDelegate delegate; MockPlatformViewDelegate delegate;
zx::eventpair a, b; zx::eventpair a, b;
...@@ -552,63 +544,13 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) { ...@@ -552,63 +544,13 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) {
nullptr // io nullptr // io
); );
// Test get view embedder callback function. // Test create surface callback function.
MockExternalViewEmbedder view_embedder;
auto GetViewEmbedderCallback = [&view_embedder]() { return &view_embedder; };
auto platform_view = flutter_runner::PlatformView(
delegate, // delegate
"test_platform_view", // label
std::move(view_ref), // view_refs
std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // focuser,
nullptr, // on_session_listener_error_callback
nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
nullptr, // on_update_view_callback,
nullptr, // on_destroy_view_callback,
GetViewEmbedderCallback, // on_get_view_embedder_callback,
nullptr, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);
RunLoopUntilIdle();
platform_view.NotifyCreated();
RunLoopUntilIdle();
EXPECT_EQ(&view_embedder, delegate.get_view_embedder());
}
// Test to make sure that PlatformView correctly returns a Surface instance
// that can surface the GrContext provided from GetGrContextCallback.
TEST_F(PlatformViewTests, GetGrContextTest) {
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
MockPlatformViewDelegate delegate;
zx::eventpair a, b;
zx::eventpair::create(/* flags */ 0u, &a, &b);
auto view_ref = fuchsia::ui::views::ViewRef({
.reference = std::move(a),
});
flutter::TaskRunners task_runners =
flutter::TaskRunners("test_runners", // label
nullptr, // platform
flutter_runner::CreateFMLTaskRunner(
async_get_default_dispatcher()), // raster
nullptr, // ui
nullptr // io
);
// Test get GrContext callback function.
sk_sp<GrDirectContext> gr_context = sk_sp<GrDirectContext> gr_context =
GrDirectContext::MakeMock(nullptr, GrContextOptions()); GrDirectContext::MakeMock(nullptr, GrContextOptions());
auto GetGrContextCallback = [gr_context = gr_context.get()]() { MockExternalViewEmbedder view_embedder;
return gr_context; auto CreateSurfaceCallback = [&view_embedder, gr_context]() {
return std::make_unique<flutter_runner::Surface>(
"PlatformViewTest", &view_embedder, gr_context.get());
}; };
auto platform_view = flutter_runner::PlatformView( auto platform_view = flutter_runner::PlatformView(
...@@ -617,27 +559,24 @@ TEST_F(PlatformViewTests, GetGrContextTest) { ...@@ -617,27 +559,24 @@ TEST_F(PlatformViewTests, GetGrContextTest) {
std::move(view_ref), // view_refs std::move(view_ref), // view_refs
std::move(task_runners), // task_runners std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request nullptr, // session_listener_request
nullptr, // focuser nullptr, // focuser,
nullptr, // on_session_listener_error_callback nullptr, // on_session_listener_error_callback
nullptr, // on_enable_wireframe_callback, nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback, nullptr, // on_create_view_callback,
nullptr, // on_update_view_callback, nullptr, // on_update_view_callback,
nullptr, // on_destroy_view_callback, nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback, CreateSurfaceCallback, // on_create_surface_callback,
GetGrContextCallback, // on_get_gr_context_callback, fml::TimeDelta::Zero(), // vsync_offset
0u, // vsync_event_handle ZX_HANDLE_INVALID // vsync_event_handle
{} // product_config
); );
RunLoopUntilIdle();
platform_view.NotifyCreated(); platform_view.NotifyCreated();
RunLoopUntilIdle(); RunLoopUntilIdle();
EXPECT_EQ(gr_context.get(), delegate.get_gr_context()); EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
EXPECT_EQ(&view_embedder, delegate.surface()->GetExternalViewEmbedder());
} }
} // namespace flutter_runner_test::flutter_runner_a11y_test } // namespace flutter_runner_test::flutter_runner_a11y_test
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册