Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flow/layers/container_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void ContainerLayer::UpdateSceneChildren(
if (child_layer_exists_below_) {
frame.emplace(
context, SkRRect::MakeRect(paint_bounds()), SK_ColorTRANSPARENT,
SkScalarRoundToInt(context->alphaf() * 255), "flutter::ContainerLayer");
SkScalarRoundToInt(context->alphaf() * 255), "flutter::Layer");
frame->AddPaintLayer(this);
}

Expand Down
8 changes: 2 additions & 6 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,19 @@ void LayerTree::UpdateScene(std::shared_ptr<SceneUpdateContext> context) {
TRACE_EVENT0("flutter", "LayerTree::UpdateScene");

// Reset for a new Scene.
context->Reset();

const float inv_dpr = 1.0f / device_pixel_ratio_;
SceneUpdateContext::Transform transform(context, inv_dpr, inv_dpr, 1.0f);
context->Reset(frame_size_, device_pixel_ratio_);

SceneUpdateContext::Frame frame(
context,
SkRRect::MakeRect(
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
SK_ColorTRANSPARENT, SK_AlphaOPAQUE, "flutter::LayerTree");
SK_ColorTRANSPARENT, SK_AlphaOPAQUE, "flutter::Layer");
if (root_layer_->needs_system_composite()) {
root_layer_->UpdateScene(context);
}
if (!root_layer_->is_empty()) {
frame.AddPaintLayer(root_layer_.get());
}
context->root_node().AddChild(transform.entity_node());
}
#endif

Expand Down
54 changes: 38 additions & 16 deletions flow/scene_update_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,26 @@ SceneUpdateContext::SceneUpdateContext(std::string debug_label,
std::move(view_ref_pair.control_ref),
std::move(view_ref_pair.view_ref),
debug_label),
root_node_(session_.get()),
intercept_all_input_(intercept_all_input) {
root_view_.AddChild(root_node_);
root_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
metrics_node_(session.get()),
layer_tree_node_(session_.get()) {
layer_tree_node_.SetLabel("Flutter::LayerTree");
metrics_node_.SetLabel("Flutter::MetricsWatcher");
metrics_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
metrics_node_.AddChild(layer_tree_node_);
root_view_.AddChild(metrics_node_);

// Set up the input interceptor at the top of the scene, if applicable. It
// will capture all input, and any unwanted input will be reinjected into
// embedded views.
if (intercept_all_input) {
input_interceptor_node_.emplace(session_.get());
input_interceptor_node_->SetLabel("Flutter::InputInterceptor");
input_interceptor_node_->SetHitTestBehavior(
fuchsia::ui::gfx::HitTestBehavior::kDefault);
input_interceptor_node_->SetSemanticVisibility(false);

metrics_node_.AddChild(input_interceptor_node_.value());
}

session_.Present();
}
Expand All @@ -97,7 +113,8 @@ void SceneUpdateContext::EnableWireframe(bool enable) {
scenic::NewSetEnableDebugViewBoundsCmd(root_view_.id(), enable));
}

void SceneUpdateContext::Reset() {
void SceneUpdateContext::Reset(const SkISize& frame_size,
float device_pixel_ratio) {
paint_tasks_.clear();
top_entity_ = nullptr;
top_scale_x_ = 1.f;
Expand All @@ -106,9 +123,22 @@ void SceneUpdateContext::Reset() {
next_elevation_ = 0.f;
alpha_ = 1.f;

// Adjust scene scaling to match the device pixel ratio.
const float inv_dpr = 1.0f / device_pixel_ratio;
metrics_node_.SetScale(inv_dpr, inv_dpr, 1.0f);

// Set up the input interceptor at the top of the scene, if applicable.
if (input_interceptor_node_.has_value()) {
// TODO(fxb/): Don't hardcode elevation.
input_interceptor_node_->SetTranslation(frame_size.width() * 0.5f,
frame_size.height() * 0.5f, -100.f);
input_interceptor_node_->SetShape(scenic::Rectangle(
session_.get(), frame_size.width(), frame_size.height()));
}

// We are going to be sending down a fresh node hierarchy every frame. So just
// enqueue a detach op on the imported root node.
session_.get()->Enqueue(scenic::NewDetachChildrenCmd(root_node_.id()));
// enqueue a detach op on the layer tree node.
layer_tree_node_.DetachChildren();
}

void SceneUpdateContext::CreateFrame(scenic::EntityNode& entity_node,
Expand Down Expand Up @@ -228,7 +258,7 @@ SceneUpdateContext::Entity::~Entity() {
if (previous_entity_) {
previous_entity_->embedder_node().AddChild(entity_node_);
} else {
context_->root_node_.AddChild(entity_node_);
context_->layer_tree_node_.AddChild(entity_node_);
}

FML_DCHECK(context_->top_entity_ == this);
Expand Down Expand Up @@ -319,14 +349,6 @@ SceneUpdateContext::Frame::Frame(std::shared_ptr<SceneUpdateContext> context,
// with opacity != 1. For now, clamp to a infinitesimally smaller value than
// 1, which does not cause visual problems in practice.
opacity_node_.SetOpacity(std::min(kOneMinusEpsilon, opacity_ / 255.0f));

if (context->intercept_all_input_) {
context->input_interceptor_.emplace(context->session_.get());
context->input_interceptor_->UpdateDimensions(
context->session_.get(), rrect.width(), rrect.height(),
-(local_elevation + kScenicZElevationBetweenLayers * 0.5f));
entity_node().AddChild(context->input_interceptor_->node());
}
}

SceneUpdateContext::Frame::~Frame() {
Expand Down
45 changes: 4 additions & 41 deletions flow/scene_update_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
bool intercept_all_input = false);
~SceneUpdateContext() = default;

scenic::ContainerNode& root_node() { return root_node_; }

// The cumulative alpha value based on all the parent OpacityLayers.
void set_alphaf(float alpha) { alpha_ = alpha; }
float alphaf() { return alpha_; }
Expand All @@ -139,7 +137,7 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
void EnableWireframe(bool enable);

// Reset state for a new frame.
void Reset();
void Reset(const SkISize& frame_size, float device_pixel_ratio);

// |ExternalViewEmbedder|
SkCanvas* GetRootCanvas() override { return nullptr; }
Expand Down Expand Up @@ -178,40 +176,6 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
std::optional<bool> override_hit_testable = std::nullopt);

private:
// Helper class for setting up an invisible rectangle to catch all input.
// Rejected input will then be re-injected into a suitable platform view
// controlled by this Engine instance.
class InputInterceptor {
public:
InputInterceptor(scenic::Session* session)
: opacity_node_(session), shape_node_(session) {
opacity_node_.SetLabel("Flutter::InputInterceptor");
opacity_node_.SetOpacity(0.f);

// Set the shape node to capture all input. Any unwanted input will be
// reinjected.
shape_node_.SetHitTestBehavior(
fuchsia::ui::gfx::HitTestBehavior::kDefault);
shape_node_.SetSemanticVisibility(false);

opacity_node_.AddChild(shape_node_);
}

void UpdateDimensions(scenic::Session* session,
float width,
float height,
float elevation) {
opacity_node_.SetTranslation(width * 0.5f, height * 0.5f, elevation);
shape_node_.SetShape(scenic::Rectangle(session, width, height));
}

const scenic::Node& node() { return opacity_node_; }

private:
scenic::OpacityNodeHACK opacity_node_;
scenic::ShapeNode shape_node_;
};

void CreateFrame(scenic::EntityNode& entity_node,
const SkRRect& rrect,
SkColor color,
Expand All @@ -222,7 +186,9 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
SessionWrapper& session_;

scenic::View root_view_;
scenic::EntityNode root_node_;
scenic::EntityNode metrics_node_;
scenic::EntityNode layer_tree_node_;
std::optional<scenic::ShapeNode> input_interceptor_node_;

std::vector<PaintTask> paint_tasks_;

Expand All @@ -234,9 +200,6 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
float next_elevation_ = 0.f;
float alpha_ = 1.f;

std::optional<InputInterceptor> input_interceptor_;
bool intercept_all_input_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext);
};

Expand Down
2 changes: 2 additions & 0 deletions shell/platform/fuchsia/flutter/component.cc
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ Application::Application(
std::string json_string;
if (dart_utils::ReadFileToString(kRunnerConfigPath, &json_string)) {
product_config_ = FlutterRunnerProductConfiguration(json_string);
FML_LOG(INFO) << "Successfully loaded runner configuration: "
<< json_string;
} else {
FML_LOG(WARNING) << "Failed to load runner configuration from "
<< kRunnerConfigPath << "; using default config values.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
// found in the LICENSE file.

#include "flutter_runner_product_configuration.h"

#include <zircon/assert.h>

#include "flutter/fml/logging.h"
#include "rapidjson/document.h"

namespace flutter_runner {
Expand All @@ -14,8 +16,11 @@ FlutterRunnerProductConfiguration::FlutterRunnerProductConfiguration(
rapidjson::Document document;
document.Parse(json_string);

if (!document.IsObject())
if (!document.IsObject()) {
FML_LOG(ERROR) << "Failed to parse configuration; using defaults: "
<< json_string;
return;
}

// Parse out all values we're expecting.
if (document.HasMember("vsync_offset_in_us")) {
Expand Down
65 changes: 43 additions & 22 deletions shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace {
// Z-fighting.
constexpr float kScenicZElevationBetweenLayers = 0.0001f;
constexpr float kScenicZElevationForPlatformView = 100.f;
constexpr float kScenicElevationForInputInterceptor = 500.f;

} // namespace

Expand All @@ -39,18 +40,24 @@ FuchsiaExternalViewEmbedder::FuchsiaExternalViewEmbedder(
std::move(view_ref_pair.view_ref),
debug_label),
metrics_node_(session_.get()),
root_node_(session_.get()),
intercept_all_input_(intercept_all_input) {
root_view_.AddChild(metrics_node_);
metrics_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
layer_tree_node_(session_.get()) {
layer_tree_node_.SetLabel("Flutter::LayerTree");
metrics_node_.SetLabel("Flutter::MetricsWatcher");
metrics_node_.AddChild(root_node_);
root_node_.SetLabel("Flutter::LayerTree");
metrics_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
metrics_node_.AddChild(layer_tree_node_);
root_view_.AddChild(metrics_node_);

// Set up the input interceptor at the top of the scene, if applicable.
if (intercept_all_input_) {
input_interceptor_.emplace(session_.get());
metrics_node_.AddChild(input_interceptor_->node());
// Set up the input interceptor at the top of the scene, if applicable. It
// will capture all input, and any unwanted input will be reinjected into
// embedded views.
if (intercept_all_input) {
input_interceptor_node_.emplace(session_.get());
input_interceptor_node_->SetLabel("Flutter::InputInterceptor");
input_interceptor_node_->SetHitTestBehavior(
fuchsia::ui::gfx::HitTestBehavior::kDefault);
input_interceptor_node_->SetSemanticVisibility(false);

metrics_node_.AddChild(input_interceptor_node_.value());
}

session_.Present();
Expand Down Expand Up @@ -124,12 +131,28 @@ void FuchsiaExternalViewEmbedder::BeginFrame(
frame_composition_order_.push_back(kRootLayerId);

// Set up the input interceptor at the top of the scene, if applicable.
if (input_interceptor_.has_value()) {
// TODO: Don't hardcode elevation.
const float kMaximumElevation = -100.f;
input_interceptor_->UpdateDimensions(session_.get(), frame_size.width(),
frame_size.height(),
kMaximumElevation);
if (input_interceptor_node_.has_value()) {
const uint64_t rect_hash =
(static_cast<uint64_t>(frame_size_.width()) << 32) +
frame_size_.height();

// Create a new rect if needed for the interceptor.
auto found_rect = scenic_interceptor_rects_.find(rect_hash);
if (found_rect == scenic_interceptor_rects_.end()) {
auto [emplaced_rect, success] =
scenic_interceptor_rects_.emplace(std::make_pair(
rect_hash, scenic::Rectangle(session_.get(), frame_size_.width(),
frame_size_.height())));
FML_DCHECK(success);

found_rect = std::move(emplaced_rect);
}

// TODO(fxb/): Don't hardcode elevation.
input_interceptor_node_->SetTranslation(
frame_size.width() * 0.5f, frame_size.height() * 0.5f,
-kScenicElevationForInputInterceptor);
input_interceptor_node_->SetShape(found_rect->second);
}
}

Expand Down Expand Up @@ -178,7 +201,7 @@ void FuchsiaExternalViewEmbedder::SubmitFrame(

// 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);
layer_tree_node_.SetScale(inv_dpr, inv_dpr, 1.0f);

bool first_layer = true;
for (const auto& layer_id : frame_composition_order_) {
Expand Down Expand Up @@ -266,7 +289,7 @@ void FuchsiaExternalViewEmbedder::SubmitFrame(
}

// Attach the ScenicView to the main scene graph.
root_node_.AddChild(view_holder.opacity_node);
layer_tree_node_.AddChild(view_holder.opacity_node);

// Account for the ScenicView's height when positioning the next layer.
embedded_views_height += kScenicZElevationForPlatformView;
Expand Down Expand Up @@ -354,7 +377,7 @@ void FuchsiaExternalViewEmbedder::SubmitFrame(
first_layer = false;

// Attach the ScenicLayer to the main scene graph.
root_node_.AddChild(scenic_layer.shape_node);
layer_tree_node_.AddChild(scenic_layer.shape_node);

// Account for the ScenicLayer's height when positioning the next layer.
scenic_layer_index++;
Expand Down Expand Up @@ -460,14 +483,12 @@ void FuchsiaExternalViewEmbedder::Reset() {
frame_dpr_ = 1.f;

// Detach the root node to prepare for the next frame.
session_.get()->Enqueue(scenic::NewDetachChildrenCmd(root_node_.id()));
layer_tree_node_.DetachChildren();

// Clear images on all layers so they aren't cached unnecesarily.
for (auto& layer : scenic_layers_) {
layer.material.SetTexture(0);
}

input_interceptor_.reset();
}

} // namespace flutter_runner
Loading