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
65 changes: 45 additions & 20 deletions shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ void FlatlandExternalViewEmbedder::PrerollCompositeEmbeddedView(
zx_handle_t handle = static_cast<zx_handle_t>(view_id);
FML_CHECK(frame_layers_.count(handle) == 0);

frame_layers_.emplace(std::make_pair(EmbedderLayerId{handle},
EmbedderLayer(frame_size_, *params)));
frame_layers_.emplace(std::make_pair(
EmbedderLayerId{handle},
EmbedderLayer(frame_size_, *params, flutter::RTreeFactory())));
frame_composition_order_.push_back(handle);
}

Expand Down Expand Up @@ -125,8 +126,9 @@ void FlatlandExternalViewEmbedder::BeginFrame(
frame_dpr_ = device_pixel_ratio;

// Create the root layer.
frame_layers_.emplace(
std::make_pair(kRootLayerId, EmbedderLayer(frame_size, std::nullopt)));
frame_layers_.emplace(std::make_pair(
kRootLayerId,
EmbedderLayer(frame_size, std::nullopt, flutter::RTreeFactory())));
frame_composition_order_.push_back(kRootLayerId);
}

Expand Down Expand Up @@ -193,6 +195,19 @@ void FlatlandExternalViewEmbedder::SubmitFrame(
}
}

// Finish recording SkPictures.
{
TRACE_EVENT0("flutter", "FinishRecordingPictures");

for (const auto& surface_index : frame_surface_indices) {
const auto& layer = frame_layers_.find(surface_index.first);
FML_CHECK(layer != frame_layers_.end());
layer->second.picture =
layer->second.recorder->finishRecordingAsPicture();
FML_CHECK(layer->second.picture != nullptr);
}
}

// Submit layers and platform views to Scenic in composition order.
{
TRACE_EVENT0("flutter", "SubmitLayers");
Expand Down Expand Up @@ -334,30 +349,43 @@ void FlatlandExternalViewEmbedder::SubmitFrame(
? fuchsia::ui::composition::BlendMode::SRC
: fuchsia::ui::composition::BlendMode::SRC_OVER);

// Set hit regions for this layer; these hit regions correspond to the
// portions of the layer on which skia drew content.
{
FML_CHECK(layer->second.rtree);
std::list<SkRect> intersection_rects =
layer->second.rtree->searchNonOverlappingDrawnRects(
SkRect::Make(layer->second.surface_size));

std::vector<fuchsia::ui::composition::HitRegion> hit_regions;
for (const SkRect& rect : intersection_rects) {
hit_regions.emplace_back();
auto& new_hit_region = hit_regions.back();
new_hit_region.region.x = rect.x();
new_hit_region.region.y = rect.y();
new_hit_region.region.width = rect.width();
new_hit_region.region.height = rect.height();
new_hit_region.hit_test =
fuchsia::ui::composition::HitTestInteraction::DEFAULT;
}

flatland_->flatland()->SetHitRegions(
flatland_layers_[flatland_layer_index].transform_id,
std::move(hit_regions));
}

// Attach the FlatlandLayer to the main scene graph.
flatland_->flatland()->AddChild(
root_transform_id_,
flatland_layers_[flatland_layer_index].transform_id);
child_transforms_.emplace_back(
flatland_layers_[flatland_layer_index].transform_id);

// Attach full-screen hit testing shield. Note that since the hit-region
// may be transformed (translated, rotated), we do not want to set
// width/height to FLT_MAX. This will cause a numeric overflow.
flatland_->flatland()->SetHitRegions(
flatland_layers_[flatland_layer_index].transform_id,
{{{0, 0, kMaxHitRegionSize, kMaxHitRegionSize},
fuchsia::ui::composition::HitTestInteraction::
SEMANTICALLY_INVISIBLE}});
}

// Reset for the next pass:
flatland_layer_index++;
}

// TODO(fxbug.dev/104956): Setting per-layer overlay hit region for Flatland
// external view embedder should match with what is being done in GFX
// external view embedder.
// 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.
Expand Down Expand Up @@ -396,13 +424,10 @@ void FlatlandExternalViewEmbedder::SubmitFrame(

const auto& layer = frame_layers_.find(surface_index.first);
FML_CHECK(layer != frame_layers_.end());
sk_sp<SkPicture> picture =
layer->second.recorder->finishRecordingAsPicture();
FML_CHECK(picture != nullptr);

canvas->setMatrix(SkMatrix::I());
canvas->clear(SK_ColorTRANSPARENT);
canvas->drawPicture(picture);
canvas->drawPicture(layer->second.picture);
canvas->flush();
}
}
Expand Down
22 changes: 17 additions & 5 deletions shell/platform/fuchsia/flutter/flatland_external_view_embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <vector>

#include "flutter/flow/embedded_views.h"
#include "flutter/flow/rtree.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/common/canvas_spy.h"
Expand Down Expand Up @@ -144,18 +145,29 @@ class FlatlandExternalViewEmbedder final

struct EmbedderLayer {
EmbedderLayer(const SkISize& frame_size,
std::optional<flutter::EmbeddedViewParams> view_params)
: embedded_view_params(std::move(view_params)),
std::optional<flutter::EmbeddedViewParams> view_params,
flutter::RTreeFactory rtree_factory)
: rtree(rtree_factory.getInstance()),
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) {}
recorder->beginRecording(SkRect::Make(frame_size),
&rtree_factory))),
surface_size(frame_size),
picture(nullptr) {}

// Records paint operations applied to this layer's `SkCanvas`.
// These records are used to determine which portions of this layer
// contain content. The embedder propagates this information to scenic, so
// that scenic can accurately decide which portions of this layer may
// interact with input.
sk_sp<flutter::RTree> rtree;

std::optional<flutter::EmbeddedViewParams> embedded_view_params;
std::unique_ptr<SkPictureRecorder> recorder;
std::unique_ptr<flutter::CanvasSpy> canvas_spy;
SkISize surface_size;
sk_sp<SkPicture> picture;
};
using EmbedderLayerId = std::optional<uint32_t>;
constexpr static EmbedderLayerId kRootLayerId = EmbedderLayerId{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ void FakeFlatland::SetHitRegions(

auto& transform = found_transform->second;
FML_CHECK(transform);
transform->num_hit_regions = regions.size();
transform->hit_regions = std::move(regions);
}

void FakeFlatland::Clear() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ std::shared_ptr<FakeTransform> CloneFakeTransform(
.children = CloneFakeTransformVector(
transform->children, transform_cache),
.content = CloneFakeContent(transform->content),
.num_hit_regions = transform->num_hit_regions,
.hit_regions = transform->hit_regions,
}));
FML_CHECK(success);

Expand Down Expand Up @@ -136,7 +136,7 @@ bool FakeTransform::operator==(const FakeTransform& other) const {
return id == other.id && translation == other.translation &&
*clip_bounds == *other.clip_bounds &&
orientation == other.orientation && children == other.children &&
content == other.content && num_hit_regions == other.num_hit_regions;
content == other.content && hit_regions == other.hit_regions;
}

bool FakeGraph::operator==(const FakeGraph& other) const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <lib/fidl/cpp/interface_request.h>
#include <zircon/types.h>

#include <algorithm>
#include <cstdint>
#include <optional>
#include <unordered_map>
Expand Down Expand Up @@ -98,6 +99,31 @@ inline bool operator==(const fuchsia::ui::composition::ImageProperties& a,
return size_equal;
}

inline bool operator==(const fuchsia::ui::composition::HitRegion& a,
const fuchsia::ui::composition::HitRegion& b) {
return a.region == b.region && a.hit_test == b.hit_test;
}

inline bool operator!=(const fuchsia::ui::composition::HitRegion& a,
const fuchsia::ui::composition::HitRegion& b) {
return !(a == b);
}

inline bool operator==(
const std::vector<fuchsia::ui::composition::HitRegion>& a,
const std::vector<fuchsia::ui::composition::HitRegion>& b) {
if (a.size() != b.size())
return false;

for (size_t i = 0; i < a.size(); ++i) {
if (a[i] != b[i]) {
return false;
}
}

return true;
}

namespace flutter_runner::testing {

constexpr static fuchsia::ui::composition::TransformId kInvalidTransformId{0};
Expand Down Expand Up @@ -194,7 +220,7 @@ struct FakeTransform {

std::vector<std::shared_ptr<FakeTransform>> children;
std::shared_ptr<FakeContent> content;
size_t num_hit_regions;
std::vector<fuchsia::ui::composition::HitRegion> hit_regions;
};

struct FakeGraph {
Expand Down
Loading