Skip to content

Commit

Permalink
Revert "[fuchsia][a11y] Set explicit hit regions per compositor layer…
Browse files Browse the repository at this point in the history
… on GFX. (flutter#33852)"

This reverts commit 0720dc1.
  • Loading branch information
naudzghebre committed Jun 28, 2022
1 parent b18909e commit 4785b0c
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 383 deletions.
115 changes: 28 additions & 87 deletions shell/platform/fuchsia/flutter/gfx_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#include <algorithm> // For std::clamp

#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkSurface.h"
Expand Down Expand Up @@ -170,9 +169,8 @@ void GfxExternalViewEmbedder::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, flutter::RTreeFactory())));
frame_layers_.emplace(std::make_pair(EmbedderLayerId{handle},
EmbedderLayer(frame_size_, *params)));
frame_composition_order_.push_back(handle);
}

Expand Down Expand Up @@ -202,9 +200,8 @@ void GfxExternalViewEmbedder::BeginFrame(
frame_dpr_ = device_pixel_ratio;

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

// Set up the input interceptor at the top of the scene, if applicable.
Expand Down Expand Up @@ -274,19 +271,6 @@ void GfxExternalViewEmbedder::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 @@ -453,18 +437,10 @@ void GfxExternalViewEmbedder::SubmitFrame(
FML_CHECK(scenic_layer_index <= scenic_layers_.size());
if (scenic_layer_index == scenic_layers_.size()) {
ScenicLayer new_layer{
.layer_node = scenic::EntityNode(session_->get()),
.image =
ScenicImage{
.shape_node = scenic::ShapeNode(session_->get()),
.material = scenic::Material(session_->get()),
},
// We'll set hit regions later.
.hit_regions = {},
.shape_node = scenic::ShapeNode(session_->get()),
.material = scenic::Material(session_->get()),
};
new_layer.layer_node.SetLabel("Flutter::Layer");
new_layer.layer_node.AddChild(new_layer.image.shape_node);
new_layer.image.shape_node.SetMaterial(new_layer.image.material);
new_layer.shape_node.SetMaterial(new_layer.material);
scenic_layers_.emplace_back(std::move(new_layer));
}

Expand Down Expand Up @@ -515,50 +491,25 @@ void GfxExternalViewEmbedder::SubmitFrame(
embedded_views_height;
auto& scenic_layer = scenic_layers_[scenic_layer_index];
auto& scenic_rect = found_rects->second[rect_index];
auto& image = scenic_layer.image;
image.shape_node.SetLabel("Flutter::Layer::Image");
image.shape_node.SetShape(scenic_rect);
image.shape_node.SetTranslation(
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);
image.material.SetColor(SK_AlphaOPAQUE, SK_AlphaOPAQUE, SK_AlphaOPAQUE,
layer_opacity);
image.material.SetTexture(surface_for_layer->GetImageId());

// We'll set hit regions expliclty on a separate ShapeNode, so the image
// itself should be unhittable and semantically invisible.
image.shape_node.SetHitTestBehavior(
fuchsia::ui::gfx::HitTestBehavior::kSuppress);
image.shape_node.SetSemanticVisibility(false);
scenic_layer.material.SetColor(SK_AlphaOPAQUE, SK_AlphaOPAQUE,
SK_AlphaOPAQUE, layer_opacity);
scenic_layer.material.SetTexture(surface_for_layer->GetImageId());

// Only the first (i.e. the bottom-most) layer should receive input.
// TODO: Workaround for invisible overlays stealing input. Remove when
// the underlying bug is fixed.
const fuchsia::ui::gfx::HitTestBehavior layer_hit_test_behavior =
first_layer ? fuchsia::ui::gfx::HitTestBehavior::kDefault
: fuchsia::ui::gfx::HitTestBehavior::kSuppress;
scenic_layer.shape_node.SetHitTestBehavior(layer_hit_test_behavior);

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

// Compute the set of non-overlapping set of bounding boxes for the
// painted content in this layer.
{
FML_CHECK(layer->second.rtree);
std::list<SkRect> intersection_rects =
layer->second.rtree->searchNonOverlappingDrawnRects(
SkRect::Make(layer->second.surface_size));

// SkRect joined_rect = SkRect::MakeEmpty();
for (const SkRect& rect : intersection_rects) {
auto paint_bounds =
scenic::Rectangle(session_->get(), rect.width(), rect.height());
auto hit_region = scenic::ShapeNode(session_->get());
hit_region.SetLabel("Flutter::Layer::HitRegion");
hit_region.SetShape(paint_bounds);
hit_region.SetTranslation(rect.centerX(), rect.centerY(),
-layer_elevation);
hit_region.SetHitTestBehavior(
fuchsia::ui::gfx::HitTestBehavior::kDefault);
hit_region.SetSemanticVisibility(true);

scenic_layer.layer_node.AddChild(hit_region);
scenic_layer.hit_regions.push_back(std::move(hit_region));
}
}
layer_tree_node_.AddChild(scenic_layer.shape_node);
}

// Reset for the next pass:
Expand All @@ -576,11 +527,7 @@ void GfxExternalViewEmbedder::SubmitFrame(
session_->Present();
}

// Flush pending skia operations.
// NOTE: This operation MUST occur AFTER the `Present() ` call above. We
// pipeline the Skia rendering work with scenic IPC, and scenic will delay
// internally until Skia is finished. So, doing this work before calling
// `Present()` would adversely affect performance.
// Render the recorded SkPictures into the surfaces.
{
TRACE_EVENT0("flutter", "RasterizeSurfaces");

Expand All @@ -601,10 +548,13 @@ void GfxExternalViewEmbedder::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(layer->second.picture);
canvas->drawPicture(picture);
canvas->flush();
}
}
Expand Down Expand Up @@ -686,16 +636,7 @@ void GfxExternalViewEmbedder::Reset() {

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

// Detach hit regions; otherwise, they may persist across frames
// incorrectly.
for (auto& hit_region : layer.hit_regions) {
hit_region.Detach();
}

// Remove cached hit regions so that we don't recreate stale ones.
layer.hit_regions.clear();
layer.material.SetTexture(0);
}
}

Expand Down
47 changes: 6 additions & 41 deletions shell/platform/fuchsia/flutter/gfx_external_view_embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#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 @@ -139,29 +138,18 @@ class GfxExternalViewEmbedder final : public flutter::ExternalViewEmbedder {

struct EmbedderLayer {
EmbedderLayer(const SkISize& frame_size,
std::optional<flutter::EmbeddedViewParams> view_params,
flutter::RTreeFactory rtree_factory)
: rtree(rtree_factory.getInstance()),
embedded_view_params(std::move(view_params)),
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(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;
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;
sk_sp<SkPicture> picture;
};
using EmbedderLayerId = std::optional<uint32_t>;
constexpr static EmbedderLayerId kRootLayerId = EmbedderLayerId{};
Expand All @@ -184,34 +172,11 @@ class GfxExternalViewEmbedder final : public flutter::ExternalViewEmbedder {
bool pending_focusable = true;
};

// GFX resources required to render a composited flutter layer (i.e. an
// SkPicture).
struct ScenicImage {
struct ScenicLayer {
scenic::ShapeNode shape_node;
scenic::Material material;
};

// All resources required to represent a flutter layer in the GFX scene
// graph. The structure of the subgraph for a particular layer is:
//
// layer_node
// / \
// image node hit regions (zero or more)
//
// NOTE: `hit_regions` must be cleared before submitting each new frame;
// otherwise, we will report stale hittable geometry to scenic.
struct ScenicLayer {
// Root of the subtree containing the scenic resources for this layer.
scenic::EntityNode layer_node;

// Scenic resources used to render this layer's image.
ScenicImage image;

// Scenic resources that specify which parts of this layer are responsive
// to input.
std::vector<scenic::ShapeNode> hit_regions;
};

std::shared_ptr<GfxSessionConnection> session_;
std::shared_ptr<SurfaceProducer> surface_producer_;

Expand Down
Loading

0 comments on commit 4785b0c

Please sign in to comment.