未验证 提交 12a37478 编写于 作者: D David Worsham 提交者: GitHub

fuchsia: Remove dead code / break dependencies (#19396)

The fuchsia code around metrics and sizing was just sending this
information through a side-channel, when the engine already had the
information available. So, delete all of it to make future CLs simpler.

Additionally, the SceneUpdateContext has many unneccesary dependencies
re: metrics and PaintTasks. Break those to make future CLs simpler.

Tested: Ran all unittests and ran workstation on Fuchsia
BUG: 53062, 53063
上级 033dd456
......@@ -4,8 +4,6 @@
#include "flutter/flow/layers/child_scene_layer.h"
#include "flutter/flow/view_holder.h"
namespace flutter {
ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id,
......@@ -19,11 +17,9 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id,
void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll");
set_needs_system_composite(true);
CheckForChildLayerBelow(context);
context->child_scene_layer_exists_below = true;
CheckForChildLayerBelow(context);
// An alpha "hole punch" is required if the frame behind us is not opaque.
if (!context->is_opaque) {
......@@ -49,15 +45,7 @@ void ChildSceneLayer::Paint(PaintContext& context) const {
void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) {
TRACE_EVENT0("flutter", "ChildSceneLayer::UpdateScene");
FML_DCHECK(needs_system_composite());
Layer::UpdateScene(context);
auto* view_holder = ViewHolder::FromId(layer_id_);
FML_DCHECK(view_holder);
view_holder->UpdateScene(context, offset_, size_,
SkScalarRoundToInt(context.alphaf() * 255),
hit_testable_);
context.UpdateView(layer_id_, offset_, size_, hit_testable_);
}
} // namespace flutter
......@@ -4,6 +4,8 @@
#include "flutter/flow/layers/container_layer.h"
#include <optional>
namespace flutter {
ContainerLayer::ContainerLayer() {}
......@@ -30,6 +32,9 @@ void ContainerLayer::PrerollChildren(PrerollContext* context,
const SkMatrix& child_matrix,
SkRect* child_paint_bounds) {
#if defined(LEGACY_FUCHSIA_EMBEDDER)
// If there is embedded Fuchsia content in the scene (a ChildSceneLayer),
// Layers that appear above the embedded content will be turned into their own
// Scenic layers.
child_layer_exists_below_ = context->child_scene_layer_exists_below;
context->child_scene_layer_exists_below = false;
#endif
......@@ -98,63 +103,20 @@ void ContainerLayer::UpdateScene(SceneUpdateContext& context) {
}
void ContainerLayer::UpdateSceneChildren(SceneUpdateContext& context) {
auto update_scene_layers = [&] {
// Paint all of the layers which need to be drawn into the container.
// These may be flattened down to a containing Scenic Frame.
for (auto& layer : layers_) {
if (layer->needs_system_composite()) {
layer->UpdateScene(context);
}
}
};
FML_DCHECK(needs_system_composite());
// If there is embedded Fuchsia content in the scene (a ChildSceneLayer),
// PhysicalShapeLayers that appear above the embedded content will be turned
// into their own Scenic layers.
std::optional<SceneUpdateContext::Frame> frame;
if (child_layer_exists_below_) {
float global_scenic_elevation =
context.GetGlobalElevationForNextScenicLayer();
float local_scenic_elevation =
global_scenic_elevation - context.scenic_elevation();
float z_translation = -local_scenic_elevation;
// Retained rendering: speedup by reusing a retained entity node if
// possible. When an entity node is reused, no paint layer is added to the
// frame so we won't call PhysicalShapeLayer::Paint.
LayerRasterCacheKey key(unique_id(), context.Matrix());
if (context.HasRetainedNode(key)) {
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
scenic::EntityNode* retained_node = context.GetRetainedNode(key);
FML_DCHECK(context.top_entity());
FML_DCHECK(retained_node->session() == context.session());
// Re-adjust the elevation.
retained_node->SetTranslation(0.f, 0.f, z_translation);
context.top_entity()->entity_node().AddChild(*retained_node);
return;
}
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
// If we can't find an existing retained surface, create one.
SceneUpdateContext::Frame frame(
frame.emplace(
context, SkRRect::MakeRect(paint_bounds()), SK_ColorTRANSPARENT,
SkScalarRoundToInt(context.alphaf() * 255),
"flutter::PhysicalShapeLayer", z_translation, this);
frame.AddPaintLayer(this);
// Node: UpdateSceneChildren needs to be called here so that |frame| is
// still in scope (and therefore alive) while UpdateSceneChildren is being
// called.
float scenic_elevation = context.scenic_elevation();
context.set_scenic_elevation(scenic_elevation + local_scenic_elevation);
update_scene_layers();
context.set_scenic_elevation(scenic_elevation);
} else {
update_scene_layers();
SkScalarRoundToInt(context.alphaf() * 255), "flutter::ContainerLayer");
frame->AddPaintLayer(this);
}
for (auto& layer : layers_) {
if (layer->needs_system_composite()) {
layer->UpdateScene(context);
}
}
}
......
......@@ -238,57 +238,17 @@ class MockSession : public fuchsia::ui::scenic::testing::Session_TestBase {
fuchsia::ui::scenic::SessionListenerPtr listener_;
};
class MockSurfaceProducerSurface
: public SceneUpdateContext::SurfaceProducerSurface {
class MockSessionWrapper : public flutter::SessionWrapper {
public:
MockSurfaceProducerSurface(scenic::Session* session, const SkISize& size)
: image_(session, 0, 0, {}), size_(size) {}
MockSessionWrapper(fuchsia::ui::scenic::SessionPtr session_ptr)
: session_(std::move(session_ptr)) {}
~MockSessionWrapper() override = default;
size_t AdvanceAndGetAge() override { return 0; }
bool FlushSessionAcquireAndReleaseEvents() override { return false; }
bool IsValid() const override { return false; }
SkISize GetSize() const override { return size_; }
void SignalWritesFinished(
const std::function<void(void)>& on_writes_committed) override {}
scenic::Image* GetImage() override { return &image_; };
sk_sp<SkSurface> GetSkiaSurface() const override { return nullptr; };
scenic::Session* get() override { return &session_; }
void Present() override { session_.Flush(); }
private:
scenic::Image image_;
SkISize size_;
};
class MockSurfaceProducer : public SceneUpdateContext::SurfaceProducer {
public:
MockSurfaceProducer(scenic::Session* session) : session_(session) {}
std::unique_ptr<SceneUpdateContext::SurfaceProducerSurface> ProduceSurface(
const SkISize& size,
const LayerRasterCacheKey& layer_key,
std::unique_ptr<scenic::EntityNode> entity_node) override {
return std::make_unique<MockSurfaceProducerSurface>(session_, size);
}
// Query a retained entity node (owned by a retained surface) for retained
// rendering.
bool HasRetainedNode(const LayerRasterCacheKey& key) const override {
return false;
}
scenic::EntityNode* GetRetainedNode(const LayerRasterCacheKey& key) override {
return nullptr;
}
void SubmitSurface(std::unique_ptr<SceneUpdateContext::SurfaceProducerSurface>
surface) override {}
private:
scenic::Session* session_;
scenic::Session session_;
};
struct TestContext {
......@@ -297,12 +257,11 @@ struct TestContext {
fml::RefPtr<fml::TaskRunner> task_runner;
// Session.
MockSession mock_session;
fidl::InterfaceRequest<fuchsia::ui::scenic::SessionListener> listener_request;
std::unique_ptr<scenic::Session> session;
MockSession mock_session;
std::unique_ptr<MockSessionWrapper> mock_session_wrapper;
// SceneUpdateContext.
std::unique_ptr<MockSurfaceProducer> mock_surface_producer;
std::unique_ptr<SceneUpdateContext> scene_update_context;
// PrerollContext.
......@@ -324,15 +283,13 @@ std::unique_ptr<TestContext> InitTest() {
fuchsia::ui::scenic::SessionListenerPtr listener;
context->listener_request = listener.NewRequest();
context->mock_session.Bind(session_ptr.NewRequest(), std::move(listener));
context->session = std::make_unique<scenic::Session>(std::move(session_ptr));
context->mock_session_wrapper =
std::make_unique<MockSessionWrapper>(std::move(session_ptr));
// Init SceneUpdateContext.
context->mock_surface_producer =
std::make_unique<MockSurfaceProducer>(context->session.get());
context->scene_update_context = std::make_unique<SceneUpdateContext>(
context->session.get(), context->mock_surface_producer.get());
context->scene_update_context->set_metrics(
fidl::MakeOptional(fuchsia::ui::gfx::Metrics{1.f, 1.f, 1.f}));
"fuchsia_layer_unittest", fuchsia::ui::views::ViewToken(),
scenic::ViewRefPair::New(), *(context->mock_session_wrapper));
// Init PrerollContext.
context->preroll_context = std::unique_ptr<PrerollContext>(new PrerollContext{
......@@ -348,7 +305,6 @@ std::unique_ptr<TestContext> InitTest() {
context->unused_texture_registry, // texture registry (not
// supported)
false, // checkerboard_offscreen_layers
100.f, // maximum depth allowed for rendering
1.f // ratio between logical and physical
});
......@@ -602,7 +558,7 @@ TEST_F(FuchsiaLayerTest, DISABLED_PhysicalShapeLayersAndChildSceneLayers) {
// against the list above.
root->UpdateScene(*(test_context->scene_update_context));
test_context->session->Flush();
test_context->mock_session_wrapper->Present();
// Run loop until idle, so that the Session receives and processes
// its method calls.
......@@ -784,7 +740,7 @@ TEST_F(FuchsiaLayerTest, DISABLED_OpacityAndTransformLayer) {
// commands against the list above.
root->UpdateScene(*(test_context->scene_update_context));
test_context->session->Flush();
test_context->mock_session_wrapper->Present();
// Run loop until idle, so that the Session receives and processes
// its method calls.
......
......@@ -58,6 +58,9 @@ Layer::AutoPrerollSaveLayerState::~AutoPrerollSaveLayerState() {
#if defined(LEGACY_FUCHSIA_EMBEDDER)
void Layer::CheckForChildLayerBelow(PrerollContext* context) {
// If there is embedded Fuchsia content in the scene (a ChildSceneLayer),
// PhysicalShapeLayers that appear above the embedded content will be turned
// into their own Scenic layers.
child_layer_exists_below_ = context->child_scene_layer_exists_below;
if (child_layer_exists_below_) {
set_needs_system_composite(true);
......@@ -65,42 +68,14 @@ void Layer::CheckForChildLayerBelow(PrerollContext* context) {
}
void Layer::UpdateScene(SceneUpdateContext& context) {
// If there is embedded Fuchsia content in the scene (a ChildSceneLayer),
// PhysicalShapeLayers that appear above the embedded content will be turned
// into their own Scenic layers.
if (child_layer_exists_below_) {
float global_scenic_elevation =
context.GetGlobalElevationForNextScenicLayer();
float local_scenic_elevation =
global_scenic_elevation - context.scenic_elevation();
float z_translation = -local_scenic_elevation;
// Retained rendering: speedup by reusing a retained entity node if
// possible. When an entity node is reused, no paint layer is added to the
// frame so we won't call PhysicalShapeLayer::Paint.
LayerRasterCacheKey key(unique_id(), context.Matrix());
if (context.HasRetainedNode(key)) {
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
scenic::EntityNode* retained_node = context.GetRetainedNode(key);
FML_DCHECK(context.top_entity());
FML_DCHECK(retained_node->session() == context.session());
// Re-adjust the elevation.
retained_node->SetTranslation(0.f, 0.f, z_translation);
context.top_entity()->entity_node().AddChild(*retained_node);
return;
}
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
// If we can't find an existing retained surface, create one.
SceneUpdateContext::Frame frame(
context, SkRRect::MakeRect(paint_bounds()), SK_ColorTRANSPARENT,
SkScalarRoundToInt(context.alphaf() * 255),
"flutter::PhysicalShapeLayer", z_translation, this);
frame.AddPaintLayer(this);
}
FML_DCHECK(needs_system_composite());
FML_DCHECK(child_layer_exists_below_);
SceneUpdateContext::Frame frame(
context, SkRRect::MakeRect(paint_bounds()), SK_ColorTRANSPARENT,
SkScalarRoundToInt(context.alphaf() * 255), "flutter::Layer");
frame.AddPaintLayer(this);
}
#endif
......
......@@ -56,14 +56,10 @@ struct PrerollContext {
const Stopwatch& ui_time;
TextureRegistry& texture_registry;
const bool checkerboard_offscreen_layers;
// These allow us to make use of the scene metrics during Preroll.
float frame_physical_depth;
float frame_device_pixel_ratio;
const float frame_device_pixel_ratio;
// These allow us to track properties like elevation, opacity, and the
// prescence of a platform view during Preroll.
float total_elevation = 0.0f;
bool has_platform_view = false;
bool is_opaque = true;
#if defined(LEGACY_FUCHSIA_EMBEDDER)
......@@ -128,10 +124,7 @@ class Layer {
TextureRegistry& texture_registry;
const RasterCache* raster_cache;
const bool checkerboard_offscreen_layers;
// These allow us to make use of the scene metrics during Paint.
float frame_physical_depth;
float frame_device_pixel_ratio;
const float frame_device_pixel_ratio;
};
// Calls SkCanvas::saveLayer and restores the layer upon destruction. Also
......
......@@ -11,15 +11,14 @@
namespace flutter {
LayerTree::LayerTree(const SkISize& frame_size,
float frame_physical_depth,
float frame_device_pixel_ratio)
LayerTree::LayerTree(const SkISize& frame_size, float device_pixel_ratio)
: frame_size_(frame_size),
frame_physical_depth_(frame_physical_depth),
frame_device_pixel_ratio_(frame_device_pixel_ratio),
device_pixel_ratio_(device_pixel_ratio),
rasterizer_tracing_threshold_(0),
checkerboard_raster_cache_images_(false),
checkerboard_offscreen_layers_(false) {}
checkerboard_offscreen_layers_(false) {
FML_CHECK(device_pixel_ratio_ != 0.0f);
}
void LayerTree::RecordBuildTime(fml::TimePoint build_start,
fml::TimePoint target_time) {
......@@ -54,32 +53,21 @@ bool LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
frame.context().ui_time(),
frame.context().texture_registry(),
checkerboard_offscreen_layers_,
frame_physical_depth_,
frame_device_pixel_ratio_};
device_pixel_ratio_};
root_layer_->Preroll(&context, frame.root_surface_transformation());
return context.surface_needs_readback;
}
#if defined(LEGACY_FUCHSIA_EMBEDDER)
void LayerTree::UpdateScene(SceneUpdateContext& context,
scenic::ContainerNode& container) {
void LayerTree::UpdateScene(SceneUpdateContext& context) {
TRACE_EVENT0("flutter", "LayerTree::UpdateScene");
// Ensure the context is aware of the view metrics.
context.set_dimensions(frame_size_, frame_physical_depth_,
frame_device_pixel_ratio_);
const auto& metrics = context.metrics();
FML_DCHECK(metrics->scale_x > 0.0f);
FML_DCHECK(metrics->scale_y > 0.0f);
FML_DCHECK(metrics->scale_z > 0.0f);
// Reset for a new Scene.
context.Reset();
SceneUpdateContext::Transform transform(context, // context
1.0f / metrics->scale_x, // X
1.0f / metrics->scale_y, // Y
1.0f / metrics->scale_z // Z
);
const float inv_dpr = 1.0f / device_pixel_ratio_;
SceneUpdateContext::Transform transform(context, inv_dpr, inv_dpr, 1.0f);
SceneUpdateContext::Frame frame(
context,
......@@ -92,7 +80,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
if (root_layer_->needs_painting()) {
frame.AddPaintLayer(root_layer_.get());
}
container.AddChild(transform.entity_node());
context.root_node().AddChild(transform.entity_node());
}
#endif
......@@ -125,8 +113,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
frame.context().texture_registry(),
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
checkerboard_offscreen_layers_,
frame_physical_depth_,
frame_device_pixel_ratio_};
device_pixel_ratio_};
if (root_layer_->needs_painting()) {
root_layer_->Paint(context);
......@@ -151,19 +138,18 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
root_surface_transformation.reset();
PrerollContext preroll_context{
nullptr, // raster_cache (don't consult the cache)
nullptr, // gr_context (used for the raster cache)
nullptr, // external view embedder
unused_stack, // mutator stack
nullptr, // SkColorSpace* dst_color_space
kGiantRect, // SkRect cull_rect
false, // layer reads from surface
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
false, // checkerboard_offscreen_layers
frame_physical_depth_, // maximum depth allowed for rendering
frame_device_pixel_ratio_ // ratio between logical and physical
nullptr, // raster_cache (don't consult the cache)
nullptr, // gr_context (used for the raster cache)
nullptr, // external view embedder
unused_stack, // mutator stack
nullptr, // SkColorSpace* dst_color_space
kGiantRect, // SkRect cull_rect
false, // layer reads from surface
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
false, // checkerboard_offscreen_layers
device_pixel_ratio_ // ratio between logical and physical
};
SkISize canvas_size = canvas->getBaseLayerSize();
......@@ -175,13 +161,12 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
canvas, // canvas
nullptr,
nullptr,
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
nullptr, // raster cache
false, // checkerboard offscreen layers
frame_physical_depth_, // maximum depth allowed for rendering
frame_device_pixel_ratio_ // ratio between logical and physical
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
nullptr, // raster cache
false, // checkerboard offscreen layers
device_pixel_ratio_ // ratio between logical and physical
};
// Even if we don't have a root layer, we still need to create an empty
......
......@@ -20,9 +20,7 @@ namespace flutter {
class LayerTree {
public:
LayerTree(const SkISize& frame_size,
float frame_physical_depth,
float frame_device_pixel_ratio);
LayerTree(const SkISize& frame_size, float device_pixel_ratio);
// Perform a preroll pass on the tree and return information about
// the tree that affects rendering this frame.
......@@ -35,8 +33,7 @@ class LayerTree {
bool ignore_raster_cache = false);
#if defined(LEGACY_FUCHSIA_EMBEDDER)
void UpdateScene(SceneUpdateContext& context,
scenic::ContainerNode& container);
void UpdateScene(SceneUpdateContext& context);
#endif
void Paint(CompositorContext::ScopedFrame& frame,
......@@ -51,8 +48,7 @@ class LayerTree {
}
const SkISize& frame_size() const { return frame_size_; }
float frame_physical_depth() const { return frame_physical_depth_; }
float frame_device_pixel_ratio() const { return frame_device_pixel_ratio_; }
float device_pixel_ratio() const { return device_pixel_ratio_; }
void RecordBuildTime(fml::TimePoint build_start, fml::TimePoint target_time);
fml::TimePoint build_start() const { return build_start_; }
......@@ -79,16 +75,13 @@ class LayerTree {
checkerboard_offscreen_layers_ = checkerboard;
}
double device_pixel_ratio() const { return frame_device_pixel_ratio_; }
private:
std::shared_ptr<Layer> root_layer_;
fml::TimePoint build_start_;
fml::TimePoint build_finish_;
fml::TimePoint target_time_;
SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels.
float frame_physical_depth_;
float frame_device_pixel_ratio_ = 1.0f; // Logical / Physical pixels ratio.
const float device_pixel_ratio_; // Logical / Physical pixels ratio.
uint32_t rasterizer_tracing_threshold_;
bool checkerboard_raster_cache_images_;
bool checkerboard_offscreen_layers_;
......
......@@ -18,7 +18,7 @@ namespace testing {
class LayerTreeTest : public CanvasTest {
public:
LayerTreeTest()
: layer_tree_(SkISize::Make(64, 64), 100.0f, 1.0f),
: layer_tree_(SkISize::Make(64, 64), 1.0f),
compositor_context_(fml::kDefaultFrameBudget),
root_transform_(SkMatrix::Translate(1.0f, 1.0f)),
scoped_frame_(compositor_context_.AcquireFrame(nullptr,
......
......@@ -38,7 +38,6 @@ class OpacityLayer : public MergedContainerLayer {
private:
SkAlpha alpha_;
SkPoint offset_;
SkRRect frameRRect_;
FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
};
......
......@@ -21,28 +21,7 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
shadow_color_(shadow_color),
elevation_(elevation),
path_(path),
isRect_(false),
clip_behavior_(clip_behavior) {
SkRect rect;
if (path.isRect(&rect)) {
isRect_ = true;
frameRRect_ = SkRRect::MakeRect(rect);
} else if (path.isRRect(&frameRRect_)) {
isRect_ = frameRRect_.isRect();
} else if (path.isOval(&rect)) {
// isRRect returns false for ovals, so we need to explicitly check isOval
// as well.
frameRRect_ = SkRRect::MakeOval(rect);
} else {
// Scenic currently doesn't provide an easy way to create shapes from
// arbitrary paths.
// For shapes that cannot be represented as a rounded rectangle we
// default to use the bounding rectangle.
// TODO(amirh): fix this once we have a way to create a Scenic shape from
// an SkPath.
frameRRect_ = SkRRect::MakeRect(path.getBounds());
}
}
clip_behavior_(clip_behavior) {}
void PhysicalShapeLayer::Preroll(PrerollContext* context,
const SkMatrix& matrix) {
......@@ -50,14 +29,9 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context,
Layer::AutoPrerollSaveLayerState save =
Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer());
context->total_elevation += elevation_;
total_elevation_ = context->total_elevation;
SkRect child_paint_bounds;
PrerollChildren(context, matrix, &child_paint_bounds);
context->total_elevation -= elevation_;
if (elevation_ == 0) {
set_paint_bounds(path_.getBounds());
} else {
......
......@@ -35,16 +35,13 @@ class PhysicalShapeLayer : public ContainerLayer {
return clip_behavior_ == Clip::antiAliasWithSaveLayer;
}
float total_elevation() const { return total_elevation_; }
float elevation() const { return elevation_; }
private:
SkColor color_;
SkColor shadow_color_;
float elevation_ = 0.0f;
float total_elevation_ = 0.0f;
SkPath path_;
bool isRect_;
SkRRect frameRRect_;
Clip clip_behavior_;
};
......
......@@ -131,7 +131,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
initial_elevation, 1.0f));
EXPECT_TRUE(layer->needs_painting());
EXPECT_FALSE(layer->needs_system_composite());
EXPECT_EQ(layer->total_elevation(), initial_elevation);
EXPECT_EQ(layer->elevation(), initial_elevation);
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
// their shadows , so we do not use the direct |Paint()| path there.
......@@ -162,7 +162,6 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
// |
// layers[1] + 2.0f = 3.0f
constexpr float initial_elevations[4] = {1.0f, 2.0f, 3.0f, 4.0f};
constexpr float total_elevations[4] = {1.0f, 3.0f, 4.0f, 8.0f};
SkPath layer_path;
layer_path.addRect(0, 0, 80, 80).close();
......@@ -187,7 +186,6 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
1.0f /* pixel_ratio */)));
EXPECT_TRUE(layers[i]->needs_painting());
EXPECT_FALSE(layers[i]->needs_system_composite());
EXPECT_EQ(layers[i]->total_elevation(), total_elevations[i]);
}
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
......
......@@ -48,7 +48,9 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
#if defined(LEGACY_FUCHSIA_EMBEDDER)
void PlatformViewLayer::UpdateScene(SceneUpdateContext& context) {
context.UpdateScene(view_id_, offset_, size_);
TRACE_EVENT0("flutter", "PlatformViewLayer::UpdateScene");
FML_DCHECK(needs_system_composite());
context.UpdateView(view_id_, offset_, size_);
}
#endif
......
......@@ -4,6 +4,8 @@
#include "flutter/flow/layers/transform_layer.h"
#include <optional>
namespace flutter {
TransformLayer::TransformLayer(const SkMatrix& transform)
......@@ -56,12 +58,12 @@ void TransformLayer::UpdateScene(SceneUpdateContext& context) {
TRACE_EVENT0("flutter", "TransformLayer::UpdateScene");
FML_DCHECK(needs_system_composite());
std::optional<SceneUpdateContext::Transform> transform;
if (!transform_.isIdentity()) {
SceneUpdateContext::Transform transform(context, transform_);
UpdateSceneChildren(context);
} else {
UpdateSceneChildren(context);
transform.emplace(context, transform_);
}
UpdateSceneChildren(context);
}
#endif
......
......@@ -169,7 +169,6 @@ std::unique_ptr<RasterCacheResult> RasterCache::RasterizeLayer(
context->texture_registry,
context->has_platform_view ? nullptr : context->raster_cache,
context->checkerboard_offscreen_layers,
context->frame_physical_depth,
context->frame_device_pixel_ratio};
if (layer->needs_painting()) {
layer->Paint(paintContext);
......
......@@ -4,6 +4,7 @@
#include "flutter/flow/scene_update_context.h"
#include <lib/ui/scenic/cpp/commands.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include "flutter/flow/layers/layer.h"
......@@ -13,10 +14,10 @@
#include "include/core/SkColor.h"
namespace flutter {
namespace {
// Helper function to generate clip planes for a scenic::EntityNode.
static void SetEntityNodeClipPlanes(scenic::EntityNode& entity_node,
const SkRect& bounds) {
void SetEntityNodeClipPlanes(scenic::EntityNode& entity_node,
const SkRect& bounds) {
const float top = bounds.top();
const float bottom = bounds.bottom();
const float left = bounds.left();
......@@ -53,20 +54,69 @@ static void SetEntityNodeClipPlanes(scenic::EntityNode& entity_node,
entity_node.SetClipPlanes(std::move(clip_planes));
}
SceneUpdateContext::SceneUpdateContext(scenic::Session* session,
SurfaceProducer* surface_producer)
: session_(session), surface_producer_(surface_producer) {
FML_DCHECK(surface_producer_ != nullptr);
void SetMaterialColor(scenic::Material& material,
SkColor color,
SkAlpha opacity) {
const SkAlpha color_alpha = static_cast<SkAlpha>(
((float)SkColorGetA(color) * (float)opacity) / 255.0f);
material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color),
color_alpha);
}
} // namespace
SceneUpdateContext::SceneUpdateContext(std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
SessionWrapper& session)
: session_(session),
root_view_(session_.get(),
std::move(view_token),
std::move(view_ref_pair.control_ref),
std::move(view_ref_pair.view_ref),
debug_label),
root_node_(session_.get()) {
root_view_.AddChild(root_node_);
root_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
session_.Present();
}
std::vector<SceneUpdateContext::PaintTask> SceneUpdateContext::GetPaintTasks() {
std::vector<PaintTask> frame_paint_tasks = std::move(paint_tasks_);
paint_tasks_.clear();
return frame_paint_tasks;
}
void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
void SceneUpdateContext::EnableWireframe(bool enable) {
session_.get()->Enqueue(
scenic::NewSetEnableDebugViewBoundsCmd(root_view_.id(), enable));
}
void SceneUpdateContext::Reset() {
paint_tasks_.clear();
top_entity_ = nullptr;
top_scale_x_ = 1.f;
top_scale_y_ = 1.f;
top_elevation_ = 0.f;
next_elevation_ = 0.f;
alpha_ = 1.f;
// 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()));
}
void SceneUpdateContext::CreateFrame(scenic::EntityNode& entity_node,
const SkRRect& rrect,
SkColor color,
SkAlpha opacity,
const SkRect& paint_bounds,
std::vector<Layer*> paint_layers,
Layer* layer) {
FML_DCHECK(!rrect.isEmpty());
std::vector<Layer*> paint_layers) {
if (rrect.isEmpty())
return;
// Frames always clip their children.
SkRect shape_bounds = rrect.getBounds();
......@@ -74,11 +124,8 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
// and possibly for its texture.
// TODO(SCN-137): Need to be able to express the radii as vectors.
scenic::ShapeNode shape_node(session());
scenic::Rectangle shape(session_, // session
rrect.width(), // width
rrect.height() // height
);
scenic::ShapeNode shape_node(session_.get());
scenic::Rectangle shape(session_.get(), rrect.width(), rrect.height());
shape_node.SetShape(shape);
shape_node.SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(),
shape_bounds.height() * 0.5f + shape_bounds.top(),
......@@ -88,155 +135,49 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
if (paint_bounds.isEmpty() || !paint_bounds.intersects(shape_bounds))
paint_layers.clear();
scenic::Material material(session());
scenic::Material material(session_.get());
shape_node.SetMaterial(material);
entity_node.AddChild(shape_node);
// Check whether a solid color will suffice.
if (paint_layers.empty()) {
if (paint_layers.empty() || shape_bounds.isEmpty()) {
SetMaterialColor(material, color, opacity);
} else {
// Apply current metrics and transformation scale factors.
const float scale_x = ScaleX();
const float scale_y = ScaleY();
// Apply a texture to the whole shape.
SetMaterialTextureAndColor(material, color, opacity, scale_x, scale_y,
shape_bounds, std::move(paint_layers), layer,
std::move(entity_node));
}
}
void SceneUpdateContext::SetMaterialTextureAndColor(
scenic::Material& material,
SkColor color,
SkAlpha opacity,
SkScalar scale_x,
SkScalar scale_y,
const SkRect& paint_bounds,
std::vector<Layer*> paint_layers,
Layer* layer,
scenic::EntityNode entity_node) {
scenic::Image* image = GenerateImageIfNeeded(
color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer,
std::move(entity_node));
if (image != nullptr) {
// The final shape's color is material_color * texture_color. The passed in
// material color was already used as a background when generating the
// texture, so set the model color to |SK_ColorWHITE| in order to allow
// using the texture's color unmodified.
SetMaterialColor(material, SK_ColorWHITE, opacity);
material.SetTexture(*image);
} else {
// No texture was needed, so apply a solid color to the whole shape.
SetMaterialColor(material, color, opacity);
}
}
void SceneUpdateContext::SetMaterialColor(scenic::Material& material,
SkColor color,
SkAlpha opacity) {
const SkAlpha color_alpha = static_cast<SkAlpha>(
((float)SkColorGetA(color) * (float)opacity) / 255.0f);
material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color),
color_alpha);
}
scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(
SkColor color,
SkScalar scale_x,
SkScalar scale_y,
const SkRect& paint_bounds,
std::vector<Layer*> paint_layers,
Layer* layer,
scenic::EntityNode entity_node) {
// Bail if there's nothing to paint.
if (paint_layers.empty())
return nullptr;
// Bail if the physical bounds are empty after rounding.
SkISize physical_size = SkISize::Make(paint_bounds.width() * scale_x,
paint_bounds.height() * scale_y);
if (physical_size.isEmpty())
return nullptr;
// Acquire a surface from the surface producer and register the paint tasks.
std::unique_ptr<SurfaceProducerSurface> surface =
surface_producer_->ProduceSurface(
physical_size,
LayerRasterCacheKey(
// Root frame has a nullptr layer
layer ? layer->unique_id() : 0, Matrix()),
std::make_unique<scenic::EntityNode>(std::move(entity_node)));
if (!surface) {
FML_LOG(ERROR) << "Could not acquire a surface from the surface producer "
"of size: "
<< physical_size.width() << "x" << physical_size.height();
return nullptr;
// Enqueue a paint task for these layers, to apply a texture to the whole
// shape.
paint_tasks_.emplace_back(PaintTask{.paint_bounds = paint_bounds,
.scale_x = top_scale_x_,
.scale_y = top_scale_y_,
.background_color = color,
.material = std::move(material),
.layers = std::move(paint_layers)});
}
auto image = surface->GetImage();
// Enqueue the paint task.
paint_tasks_.push_back({.surface = std::move(surface),
.left = paint_bounds.left(),
.top = paint_bounds.top(),
.scale_x = scale_x,
.scale_y = scale_y,
.background_color = color,
.layers = std::move(paint_layers)});
return image;
}
std::vector<
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>>
SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
TRACE_EVENT0("flutter", "SceneUpdateContext::ExecutePaintTasks");
std::vector<std::unique_ptr<SurfaceProducerSurface>> surfaces_to_submit;
for (auto& task : paint_tasks_) {
FML_DCHECK(task.surface);
SkCanvas* canvas = task.surface->GetSkiaSurface()->getCanvas();
Layer::PaintContext context = {canvas,
canvas,
frame.gr_context(),
nullptr,
frame.context().raster_time(),
frame.context().ui_time(),
frame.context().texture_registry(),
&frame.context().raster_cache(),
false,
frame_physical_depth_,
frame_device_pixel_ratio_};
canvas->restoreToCount(1);
canvas->save();
canvas->clear(task.background_color);
canvas->scale(task.scale_x, task.scale_y);
canvas->translate(-task.left, -task.top);
for (Layer* layer : task.layers) {
layer->Paint(context);
}
surfaces_to_submit.emplace_back(std::move(task.surface));
}
paint_tasks_.clear();
alpha_ = 1.f;
topmost_global_scenic_elevation_ = kScenicZElevationBetweenLayers;
scenic_elevation_ = 0.f;
return surfaces_to_submit;
}
void SceneUpdateContext::UpdateScene(int64_t view_id,
const SkPoint& offset,
const SkSize& size) {
void SceneUpdateContext::UpdateView(int64_t view_id,
const SkPoint& offset,
const SkSize& size,
std::optional<bool> override_hit_testable) {
auto* view_holder = ViewHolder::FromId(view_id);
FML_DCHECK(view_holder);
view_holder->SetProperties(size.width(), size.height(), 0, 0, 0, 0,
view_holder->focusable());
view_holder->UpdateScene(*this, offset, size,
SkScalarRoundToInt(alphaf() * 255),
view_holder->hit_testable());
if (size.width() > 0.f && size.height() > 0.f) {
view_holder->SetProperties(size.width(), size.height(), 0, 0, 0, 0,
view_holder->focusable());
}
bool hit_testable = override_hit_testable.has_value()
? *override_hit_testable
: view_holder->hit_testable();
view_holder->UpdateScene(session_.get(), top_entity_->embedder_node(), offset,
size, SkScalarRoundToInt(alphaf() * 255),
hit_testable);
}
void SceneUpdateContext::CreateView(int64_t view_id,
......@@ -260,13 +201,17 @@ void SceneUpdateContext::DestroyView(int64_t view_id) {
SceneUpdateContext::Entity::Entity(SceneUpdateContext& context)
: context_(context),
previous_entity_(context.top_entity_),
entity_node_(context.session()) {
if (previous_entity_)
previous_entity_->embedder_node().AddChild(entity_node_);
entity_node_(context.session_.get()) {
context.top_entity_ = this;
}
SceneUpdateContext::Entity::~Entity() {
if (previous_entity_) {
previous_entity_->embedder_node().AddChild(entity_node_);
} else {
context_.root_node_.AddChild(entity_node_);
}
FML_DCHECK(context_.top_entity_ == this);
context_.top_entity_ = previous_entity_;
}
......@@ -329,18 +274,20 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
const SkRRect& rrect,
SkColor color,
SkAlpha opacity,
std::string label,
float z_translation,
Layer* layer)
std::string label)
: Entity(context),
previous_elevation_(context.top_elevation_),
rrect_(rrect),
color_(color),
opacity_(opacity),
opacity_node_(context.session()),
paint_bounds_(SkRect::MakeEmpty()),
layer_(layer) {
opacity_node_(context.session_.get()),
paint_bounds_(SkRect::MakeEmpty()) {
entity_node().SetLabel(label);
entity_node().SetTranslation(0.f, 0.f, z_translation);
entity_node().SetTranslation(0.f, 0.f,
context.next_elevation_ - previous_elevation_);
context.top_elevation_ += kScenicZElevationBetweenLayers;
context.next_elevation_ += kScenicZElevationBetweenLayers;
entity_node().AddChild(opacity_node_);
// Scenic currently lacks an API to enable rendering of alpha channel; alpha
// channels are only rendered if there is a OpacityNode higher in the tree
......@@ -350,20 +297,11 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
}
SceneUpdateContext::Frame::~Frame() {
// We don't need a shape if the frame is zero size.
if (rrect_.isEmpty())
return;
// isEmpty should account for this, but we are adding these experimental
// checks to validate if this is the root cause for b/144933519.
if (std::isnan(rrect_.width()) || std::isnan(rrect_.height())) {
FML_LOG(ERROR) << "Invalid RoundedRectangle";
return;
}
// Add a part which represents the frame's geometry for clipping purposes
context().CreateFrame(std::move(entity_node()), rrect_, color_, opacity_,
paint_bounds_, std::move(paint_layers_), layer_);
context().CreateFrame(entity_node(), rrect_, color_, opacity_, paint_bounds_,
std::move(paint_layers_));
context().top_elevation_ = previous_elevation_;
}
void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
......
......@@ -5,18 +5,19 @@
#ifndef FLUTTER_FLOW_SCENE_UPDATE_CONTEXT_H_
#define FLUTTER_FLOW_SCENE_UPDATE_CONTEXT_H_
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/session.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <cfloat>
#include <memory>
#include <set>
#include <vector>
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/raster_cache_key.h"
#include "flutter/fml/compiler_specific.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "lib/ui/scenic/cpp/resources.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkSurface.h"
......@@ -33,50 +34,16 @@ constexpr float kOneMinusEpsilon = 1 - FLT_EPSILON;
// How much layers are separated in Scenic z elevation.
constexpr float kScenicZElevationBetweenLayers = 10.f;
class SceneUpdateContext : public flutter::ExternalViewEmbedder {
class SessionWrapper {
public:
class SurfaceProducerSurface {
public:
virtual ~SurfaceProducerSurface() = default;
virtual size_t AdvanceAndGetAge() = 0;
virtual bool FlushSessionAcquireAndReleaseEvents() = 0;
virtual bool IsValid() const = 0;
virtual ~SessionWrapper() {}
virtual SkISize GetSize() const = 0;
virtual void SignalWritesFinished(
const std::function<void(void)>& on_writes_committed) = 0;
virtual scenic::Image* GetImage() = 0;
virtual sk_sp<SkSurface> GetSkiaSurface() const = 0;
};
class SurfaceProducer {
public:
virtual ~SurfaceProducer() = default;
// The produced surface owns the entity_node and has a layer_key for
// retained rendering. The surface will only be retained if the layer_key
// has a non-null layer pointer (layer_key.id()).
virtual std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
const SkISize& size,
const LayerRasterCacheKey& layer_key,
std::unique_ptr<scenic::EntityNode> entity_node) = 0;
// Query a retained entity node (owned by a retained surface) for retained
// rendering.
virtual bool HasRetainedNode(const LayerRasterCacheKey& key) const = 0;
virtual scenic::EntityNode* GetRetainedNode(
const LayerRasterCacheKey& key) = 0;
virtual void SubmitSurface(
std::unique_ptr<SurfaceProducerSurface> surface) = 0;
};
virtual scenic::Session* get() = 0;
virtual void Present() = 0;
};
class SceneUpdateContext : public flutter::ExternalViewEmbedder {
public:
class Entity {
public:
Entity(SceneUpdateContext& context);
......@@ -116,9 +83,7 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
const SkRRect& rrect,
SkColor color,
SkAlpha opacity,
std::string label,
float z_translation = 0.0f,
Layer* layer = nullptr);
std::string label);
virtual ~Frame();
scenic::ContainerNode& embedder_node() override { return opacity_node_; }
......@@ -126,6 +91,8 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
void AddPaintLayer(Layer* layer);
private:
const float previous_elevation_;
const SkRRect rrect_;
SkColor const color_;
SkAlpha const opacity_;
......@@ -133,7 +100,6 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
scenic::OpacityNodeHACK opacity_node_;
std::vector<Layer*> paint_layers_;
SkRect paint_bounds_;
Layer* layer_;
};
class Clip : public Entity {
......@@ -142,68 +108,35 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
~Clip() = default;
};
SceneUpdateContext(scenic::Session* session,
SurfaceProducer* surface_producer);
~SceneUpdateContext() = default;
scenic::Session* session() { return session_; }
struct PaintTask {
SkRect paint_bounds;
SkScalar scale_x;
SkScalar scale_y;
SkColor background_color;
scenic::Material material;
std::vector<Layer*> layers;
};
Entity* top_entity() { return top_entity_; }
SceneUpdateContext(std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
SessionWrapper& session);
~SceneUpdateContext() = default;
bool has_metrics() const { return !!metrics_; }
void set_metrics(fuchsia::ui::gfx::MetricsPtr metrics) {
metrics_ = std::move(metrics);
}
const fuchsia::ui::gfx::MetricsPtr& metrics() const { return metrics_; }
void set_dimensions(const SkISize& frame_physical_size,
float frame_physical_depth,
float frame_device_pixel_ratio) {
frame_physical_size_ = frame_physical_size;
frame_physical_depth_ = frame_physical_depth;
frame_device_pixel_ratio_ = frame_device_pixel_ratio;
}
const SkISize& frame_size() const { return frame_physical_size_; }
float frame_physical_depth() const { return frame_physical_depth_; }
float frame_device_pixel_ratio() const { return frame_device_pixel_ratio_; }
// TODO(chinmaygarde): This method must submit the surfaces as soon as paint
// tasks are done. However, given that there is no support currently for
// Vulkan semaphores, we need to submit all the surfaces after an explicit
// CPU wait. Once Vulkan semaphores are available, this method must return
// void and the implementation must submit surfaces on its own as soon as the
// specific canvas operations are done.
[[nodiscard]] std::vector<std::unique_ptr<SurfaceProducerSurface>>
ExecutePaintTasks(CompositorContext::ScopedFrame& frame);
float ScaleX() const { return metrics_->scale_x * top_scale_x_; }
float ScaleY() const { return metrics_->scale_y * top_scale_y_; }
// The transformation matrix of the current context. It's used to construct
// the LayerRasterCacheKey for a given layer.
SkMatrix Matrix() const { return SkMatrix::MakeScale(ScaleX(), ScaleY()); }
bool HasRetainedNode(const LayerRasterCacheKey& key) const {
return surface_producer_->HasRetainedNode(key);
}
scenic::EntityNode* GetRetainedNode(const LayerRasterCacheKey& key) {
return surface_producer_->GetRetainedNode(key);
}
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_; }
// The global scenic elevation at a given point in the traversal.
float scenic_elevation() { return scenic_elevation_; }
// Returns all `PaintTask`s generated for the current frame.
std::vector<PaintTask> GetPaintTasks();
void set_scenic_elevation(float elevation) { scenic_elevation_ = elevation; }
// Enable/disable wireframe rendering around the root view bounds.
void EnableWireframe(bool enable);
float GetGlobalElevationForNextScenicLayer() {
float elevation = topmost_global_scenic_elevation_;
topmost_global_scenic_elevation_ += kScenicZElevationBetweenLayers;
return elevation;
}
// Reset state for a new frame.
void Reset();
// |ExternalViewEmbedder|
SkCanvas* GetRootCanvas() override { return nullptr; }
......@@ -234,73 +167,34 @@ class SceneUpdateContext : public flutter::ExternalViewEmbedder {
}
void CreateView(int64_t view_id, bool hit_testable, bool focusable);
void DestroyView(int64_t view_id);
void UpdateScene(int64_t view_id, const SkPoint& offset, const SkSize& size);
void UpdateView(int64_t view_id,
const SkPoint& offset,
const SkSize& size,
std::optional<bool> override_hit_testable = std::nullopt);
private:
struct PaintTask {
std::unique_ptr<SurfaceProducerSurface> surface;
SkScalar left;
SkScalar top;
SkScalar scale_x;
SkScalar scale_y;
SkColor background_color;
std::vector<Layer*> layers;
};
// Setup the entity_node as a frame that materialize all the paint_layers. In
// most cases, this creates a VulkanSurface (SurfaceProducerSurface) by
// calling SetShapeTextureOrColor and GenerageImageIfNeeded. Such surface will
// own the associated entity_node. If the layer pointer isn't nullptr, the
// surface (and thus the entity_node) will be retained for that layer to
// improve the performance.
void CreateFrame(scenic::EntityNode entity_node,
void CreateFrame(scenic::EntityNode& entity_node,
const SkRRect& rrect,
SkColor color,
SkAlpha opacity,
const SkRect& paint_bounds,
std::vector<Layer*> paint_layers,
Layer* layer);
void SetMaterialTextureAndColor(scenic::Material& material,
SkColor color,
SkAlpha opacity,
SkScalar scale_x,
SkScalar scale_y,
const SkRect& paint_bounds,
std::vector<Layer*> paint_layers,
Layer* layer,
scenic::EntityNode entity_node);
void SetMaterialColor(scenic::Material& material,
SkColor color,
SkAlpha opacity);
scenic::Image* GenerateImageIfNeeded(SkColor color,
SkScalar scale_x,
SkScalar scale_y,
const SkRect& paint_bounds,
std::vector<Layer*> paint_layers,
Layer* layer,
scenic::EntityNode entity_node);
std::vector<Layer*> paint_layers);
Entity* top_entity_ = nullptr;
float top_scale_x_ = 1.f;
float top_scale_y_ = 1.f;
SessionWrapper& session_;
scenic::Session* const session_;
SurfaceProducer* const surface_producer_;
scenic::View root_view_;
scenic::EntityNode root_node_;
fuchsia::ui::gfx::MetricsPtr metrics_;
SkISize frame_physical_size_;
float frame_physical_depth_ = 0.0f;
float frame_device_pixel_ratio_ =
1.0f; // Ratio between logical and physical pixels.
std::vector<PaintTask> paint_tasks_;
float alpha_ = 1.0f;
float scenic_elevation_ = 0.f;
float topmost_global_scenic_elevation_ = kScenicZElevationBetweenLayers;
Entity* top_entity_ = nullptr;
float top_scale_x_ = 1.f;
float top_scale_y_ = 1.f;
float top_elevation_ = 0.f;
std::vector<PaintTask> paint_tasks_;
float next_elevation_ = 0.f;
float alpha_ = 1.f;
FML_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext);
};
......
......@@ -47,11 +47,9 @@ class LayerTestBase : public CanvasTestBase<BaseT> {
kGiantRect, /* cull_rect */
false, /* layer reads from surface */
raster_time_, ui_time_, texture_registry_,
false, /* checkerboard_offscreen_layers */
100.0f, /* frame_physical_depth */
1.0f, /* frame_device_pixel_ratio */
0.0f, /* total_elevation */
false, /* has_platform_view */
false, /* checkerboard_offscreen_layers */
1.0f, /* frame_device_pixel_ratio */
false, /* has_platform_view */
}),
paint_context_({
TestT::mock_canvas().internal_canvas(), /* internal_nodes_canvas */
......@@ -61,7 +59,6 @@ class LayerTestBase : public CanvasTestBase<BaseT> {
raster_time_, ui_time_, texture_registry_,
nullptr, /* raster_cache */
false, /* checkerboard_offscreen_layers */
100.0f, /* frame_physical_depth */
1.0f, /* frame_device_pixel_ratio */
}) {
use_null_raster_cache();
......
......@@ -22,7 +22,6 @@ void MockLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
parent_mutators_ = context->mutators_stack;
parent_matrix_ = matrix;
parent_cull_rect_ = context->cull_rect;
parent_elevation_ = context->total_elevation;
parent_has_platform_view_ = context->has_platform_view;
context->has_platform_view = fake_has_platform_view_;
......
......@@ -28,7 +28,6 @@ class MockLayer : public Layer {
const MutatorsStack& parent_mutators() { return parent_mutators_; }
const SkMatrix& parent_matrix() { return parent_matrix_; }
const SkRect& parent_cull_rect() { return parent_cull_rect_; }
float parent_elevation() { return parent_elevation_; }
bool parent_has_platform_view() { return parent_has_platform_view_; }
private:
......@@ -37,7 +36,6 @@ class MockLayer : public Layer {
SkRect parent_cull_rect_ = SkRect::MakeEmpty();
SkPath fake_paint_path_;
SkPaint fake_paint_;
float parent_elevation_ = 0;
bool parent_has_platform_view_ = false;
bool fake_has_platform_view_ = false;
bool fake_needs_system_composite_ = false;
......
......@@ -39,13 +39,11 @@ TEST_F(MockLayerTest, SimpleParams) {
const SkMatrix start_matrix = SkMatrix::Translate(1.0f, 2.0f);
const SkMatrix scale_matrix = SkMatrix::Scale(0.5f, 0.5f);
const SkRect cull_rect = SkRect::MakeWH(5.0f, 5.0f);
const float parent_elevation = 5.0f;
const bool parent_has_platform_view = true;
auto layer = std::make_shared<MockLayer>(path, paint);
preroll_context()->mutators_stack.PushTransform(scale_matrix);
preroll_context()->cull_rect = cull_rect;
preroll_context()->total_elevation = parent_elevation;
preroll_context()->has_platform_view = parent_has_platform_view;
layer->Preroll(preroll_context(), start_matrix);
EXPECT_EQ(preroll_context()->has_platform_view, false);
......@@ -55,7 +53,6 @@ TEST_F(MockLayerTest, SimpleParams) {
EXPECT_EQ(layer->parent_mutators(), std::vector{Mutator(scale_matrix)});
EXPECT_EQ(layer->parent_matrix(), start_matrix);
EXPECT_EQ(layer->parent_cull_rect(), cull_rect);
EXPECT_EQ(layer->parent_elevation(), parent_elevation);
EXPECT_EQ(layer->parent_has_platform_view(), parent_has_platform_view);
layer->Paint(paint_context());
......
......@@ -4,6 +4,8 @@
#include "flutter/flow/view_holder.h"
#include <unordered_map>
#include "flutter/fml/thread_local.h"
namespace {
......@@ -98,18 +100,17 @@ ViewHolder::ViewHolder(fml::RefPtr<fml::TaskRunner> ui_task_runner,
FML_DCHECK(pending_view_holder_token_.value);
}
void ViewHolder::UpdateScene(SceneUpdateContext& context,
void ViewHolder::UpdateScene(scenic::Session* session,
scenic::ContainerNode& container_node,
const SkPoint& offset,
const SkSize& size,
SkAlpha opacity,
bool hit_testable) {
if (pending_view_holder_token_.value) {
entity_node_ = std::make_unique<scenic::EntityNode>(context.session());
opacity_node_ =
std::make_unique<scenic::OpacityNodeHACK>(context.session());
entity_node_ = std::make_unique<scenic::EntityNode>(session);
opacity_node_ = std::make_unique<scenic::OpacityNodeHACK>(session);
view_holder_ = std::make_unique<scenic::ViewHolder>(
context.session(), std::move(pending_view_holder_token_),
"Flutter SceneHost");
session, std::move(pending_view_holder_token_), "Flutter SceneHost");
opacity_node_->AddChild(*entity_node_);
opacity_node_->SetLabel("flutter::ViewHolder");
entity_node_->Attach(*view_holder_);
......@@ -125,7 +126,7 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context,
FML_DCHECK(opacity_node_);
FML_DCHECK(view_holder_);
context.top_entity()->embedder_node().AddChild(*opacity_node_);
container_node.AddChild(*opacity_node_);
opacity_node_->SetOpacity(opacity / 255.0f);
entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f);
entity_node_->SetHitTestBehavior(
......
......@@ -9,17 +9,17 @@
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/ui/scenic/cpp/id.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/session.h>
#include <zircon/types.h>
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkSize.h"
#include <memory>
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/task_runner.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkSize.h"
namespace flutter {
......@@ -54,7 +54,8 @@ class ViewHolder {
// Creates or updates the contained ViewHolder resource using the specified
// |SceneUpdateContext|.
void UpdateScene(SceneUpdateContext& context,
void UpdateScene(scenic::Session* session,
scenic::ContainerNode& container_node,
const SkPoint& offset,
const SkSize& size,
SkAlpha opacity,
......
......@@ -50,7 +50,6 @@ Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
layer_tree_ = std::make_unique<LayerTree>(
SkISize::Make(viewport_metrics.physical_width,
viewport_metrics.physical_height),
static_cast<float>(viewport_metrics.physical_depth),
static_cast<float>(viewport_metrics.device_pixel_ratio));
layer_tree_->set_root_layer(std::move(rootLayer));
layer_tree_->set_rasterizer_tracing_threshold(rasterizerTracingThreshold);
......
......@@ -14,7 +14,6 @@ void _updateWindowMetrics(
double devicePixelRatio,
double width,
double height,
double depth,
double viewPaddingTop,
double viewPaddingRight,
double viewPaddingBottom,
......@@ -31,7 +30,6 @@ void _updateWindowMetrics(
window
.._devicePixelRatio = devicePixelRatio
.._physicalSize = Size(width, height)
.._physicalDepth = depth
.._viewPadding = WindowPadding._(
top: viewPaddingTop,
right: viewPaddingRight,
......
......@@ -627,20 +627,6 @@ class Window {
Size get physicalSize => _physicalSize;
Size _physicalSize = Size.zero;
/// The physical depth is the maximum elevation that the Window allows.
///
/// Physical layers drawn at or above this elevation will have their elevation
/// clamped to this value. This can happen if the physical layer itself has
/// an elevation larger than available depth, or if some ancestor of the layer
/// causes it to have a cumulative elevation that is larger than the available
/// depth.
///
/// The default value is [double.maxFinite], which is used for platforms that
/// do not specify a maximum elevation. This property is currently on expected
/// to be set to a non-default value on Fuchsia.
double get physicalDepth => _physicalDepth;
double _physicalDepth = double.maxFinite;
/// The number of physical pixels on each side of the display rectangle into
/// which the application can render, but over which the operating system
/// will likely place system UI, such as the keyboard, that fully obscures
......
......@@ -8,6 +8,8 @@
namespace flutter {
ViewportMetrics::ViewportMetrics() = default;
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height,
......@@ -46,40 +48,6 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
FML_DCHECK(device_pixel_ratio > 0);
}
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height,
double p_physical_depth,
double p_physical_padding_top,
double p_physical_padding_right,
double p_physical_padding_bottom,
double p_physical_padding_left,
double p_physical_view_inset_front,
double p_physical_view_inset_back,
double p_physical_view_inset_top,
double p_physical_view_inset_right,
double p_physical_view_inset_bottom,
double p_physical_view_inset_left)
: device_pixel_ratio(p_device_pixel_ratio),
physical_width(p_physical_width),
physical_height(p_physical_height),
physical_depth(p_physical_depth),
physical_padding_top(p_physical_padding_top),
physical_padding_right(p_physical_padding_right),
physical_padding_bottom(p_physical_padding_bottom),
physical_padding_left(p_physical_padding_left),
physical_view_inset_top(p_physical_view_inset_top),
physical_view_inset_right(p_physical_view_inset_right),
physical_view_inset_bottom(p_physical_view_inset_bottom),
physical_view_inset_left(p_physical_view_inset_left),
physical_view_inset_front(p_physical_view_inset_front),
physical_view_inset_back(p_physical_view_inset_back) {
// Ensure we don't have nonsensical dimensions.
FML_DCHECK(physical_width >= 0);
FML_DCHECK(physical_height >= 0);
FML_DCHECK(device_pixel_ratio > 0);
}
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height)
......
......@@ -5,21 +5,10 @@
#ifndef FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_
#define FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_
#include <stdint.h>
namespace flutter {
// This is the value of double.maxFinite from dart:core.
// Platforms that do not explicitly set a depth will use this value, which
// avoids the need to special case logic that wants to check the max depth on
// the Dart side.
static const double kUnsetDepth = 1.7976931348623157e+308;
struct ViewportMetrics {
ViewportMetrics() = default;
ViewportMetrics(const ViewportMetrics& other) = default;
// Create a 2D ViewportMetrics instance.
ViewportMetrics();
ViewportMetrics(double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height,
......@@ -36,22 +25,6 @@ struct ViewportMetrics {
double p_physical_system_gesture_inset_bottom,
double p_physical_system_gesture_inset_left);
// Create a ViewportMetrics instance that contains z information.
ViewportMetrics(double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height,
double p_physical_depth,
double p_physical_padding_top,
double p_physical_padding_right,
double p_physical_padding_bottom,
double p_physical_padding_left,
double p_physical_view_inset_front,
double p_physical_view_inset_back,
double p_physical_view_inset_top,
double p_physical_view_inset_right,
double p_physical_view_inset_bottom,
double p_physical_view_inset_left);
// Create a ViewportMetrics instance that doesn't include depth, padding, or
// insets.
ViewportMetrics(double p_device_pixel_ratio,
......@@ -61,7 +34,6 @@ struct ViewportMetrics {
double device_pixel_ratio = 1.0;
double physical_width = 0;
double physical_height = 0;
double physical_depth = kUnsetDepth;
double physical_padding_top = 0;
double physical_padding_right = 0;
double physical_padding_bottom = 0;
......@@ -70,8 +42,6 @@ struct ViewportMetrics {
double physical_view_inset_right = 0;
double physical_view_inset_bottom = 0;
double physical_view_inset_left = 0;
double physical_view_inset_front = kUnsetDepth;
double physical_view_inset_back = kUnsetDepth;
double physical_system_gesture_inset_top = 0;
double physical_system_gesture_inset_right = 0;
double physical_system_gesture_inset_bottom = 0;
......@@ -81,7 +51,6 @@ struct ViewportMetrics {
struct LogicalSize {
double width = 0.0;
double height = 0.0;
double depth = kUnsetDepth;
};
struct LogicalInset {
......@@ -89,14 +58,11 @@ struct LogicalInset {
double top = 0.0;
double right = 0.0;
double bottom = 0.0;
double front = kUnsetDepth;
double back = kUnsetDepth;
};
struct LogicalMetrics {
LogicalSize size;
double scale = 1.0;
double scale_z = 1.0;
LogicalInset padding;
LogicalInset view_inset;
};
......
......@@ -49,7 +49,6 @@ void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
tonic::ToDart(metrics.device_pixel_ratio),
tonic::ToDart(metrics.physical_width),
tonic::ToDart(metrics.physical_height),
tonic::ToDart(metrics.physical_depth),
tonic::ToDart(metrics.physical_padding_top),
tonic::ToDart(metrics.physical_padding_right),
tonic::ToDart(metrics.physical_padding_bottom),
......
......@@ -146,9 +146,6 @@ class EngineWindow extends ui.Window {
/// Overrides the value of [physicalSize] in tests.
ui.Size? webOnlyDebugPhysicalSizeOverride;
@override
double get physicalDepth => double.maxFinite;
/// Handles the browser history integration to allow users to use the back
/// button, etc.
final BrowserHistory _browserHistory = BrowserHistory();
......
......@@ -455,19 +455,6 @@ abstract class Window {
/// observe when this value changes.
Size get physicalSize;
/// The physical depth is the maximum elevation that the Window allows.
///
/// Physical layers drawn at or above this elevation will have their elevation
/// clamped to this value. This can happen if the physical layer itself has
/// an elevation larger than available depth, or if some ancestor of the layer
/// causes it to have a cumulative elevation that is larger than the available
/// depth.
///
/// The default value is [double.maxFinite], which is used for platforms that
/// do not specify a maximum elevation. This property is currently on expected
/// to be set to a non-default value on Fuchsia.
double get physicalDepth;
/// The number of physical pixels on each side of the display rectangle into
/// which the application can render, but over which the operating system
/// will likely place system UI, such as the keyboard, that fully obscures
......
......@@ -276,7 +276,6 @@ void Engine::SetViewportMetrics(const ViewportMetrics& metrics) {
bool dimensions_changed =
viewport_metrics_.physical_height != metrics.physical_height ||
viewport_metrics_.physical_width != metrics.physical_width ||
viewport_metrics_.physical_depth != metrics.physical_depth ||
viewport_metrics_.device_pixel_ratio != metrics.device_pixel_ratio;
viewport_metrics_ = metrics;
runtime_controller_->SetViewportMetrics(viewport_metrics_);
......@@ -462,8 +461,7 @@ void Engine::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
// Ensure frame dimensions are sane.
if (layer_tree->frame_size().isEmpty() ||
layer_tree->frame_physical_depth() <= 0.0f ||
layer_tree->frame_device_pixel_ratio() <= 0.0f) {
layer_tree->device_pixel_ratio() <= 0.0f) {
return;
}
......
......@@ -129,7 +129,6 @@ void ShellTest::PumpOneFrame(Shell* shell,
auto layer_tree = std::make_unique<LayerTree>(
SkISize::Make(viewport_metrics.physical_width,
viewport_metrics.physical_height),
static_cast<float>(viewport_metrics.physical_depth),
static_cast<float>(viewport_metrics.device_pixel_ratio));
SkMatrix identity;
identity.setIdentity();
......
......@@ -12,7 +12,6 @@ import("//flutter/tools/fuchsia/dart.gni")
import("//flutter/tools/fuchsia/fuchsia_archive.gni")
import("//flutter/tools/fuchsia/fuchsia_libs.gni")
import("//flutter/vulkan/config.gni")
import("engine_flutter_runner.gni")
# Fuchsia uses its own custom Surface implementation.
shell_gpu_configuration("fuchsia_legacy_gpu_configuration") {
......@@ -22,10 +21,158 @@ shell_gpu_configuration("fuchsia_legacy_gpu_configuration") {
enable_metal = false
}
source_set("flutter_runner_sources") {
sources = [
"accessibility_bridge.cc",
"accessibility_bridge.h",
"component.cc",
"component.h",
"compositor_context.cc",
"compositor_context.h",
"engine.cc",
"engine.h",
"flutter_runner_product_configuration.cc",
"flutter_runner_product_configuration.h",
"fuchsia_intl.cc",
"fuchsia_intl.h",
"isolate_configurator.cc",
"isolate_configurator.h",
"logging.h",
"loop.cc",
"loop.h",
"platform_view.cc",
"platform_view.h",
"runner.cc",
"runner.h",
"session_connection.cc",
"session_connection.h",
"surface.cc",
"surface.h",
"task_observers.cc",
"task_observers.h",
"task_runner_adapter.cc",
"task_runner_adapter.h",
"thread.cc",
"thread.h",
"unique_fdio_ns.h",
"vsync_recorder.cc",
"vsync_recorder.h",
"vsync_waiter.cc",
"vsync_waiter.h",
"vulkan_surface.cc",
"vulkan_surface.h",
"vulkan_surface_pool.cc",
"vulkan_surface_pool.h",
"vulkan_surface_producer.cc",
"vulkan_surface_producer.h",
]
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_public_deps = [
"//flutter/flow:flow_fuchsia_legacy",
"//flutter/lib/ui:ui_fuchsia_legacy",
"//flutter/runtime:runtime_fuchsia_legacy",
"//flutter/shell/common:common_fuchsia_legacy",
]
flutter_deps = [
":fuchsia_legacy_gpu_configuration",
"//flutter/assets",
"//flutter/common",
"//flutter/fml",
"//flutter/vulkan",
]
public_deps = [
"$fuchsia_sdk_root/pkg:scenic_cpp",
"$fuchsia_sdk_root/pkg:sys_cpp",
"//flutter/shell/platform/fuchsia/runtime/dart/utils",
] + flutter_public_deps
deps = [
"$fuchsia_sdk_root/fidl:fuchsia.accessibility.semantics",
"$fuchsia_sdk_root/fidl:fuchsia.fonts",
"$fuchsia_sdk_root/fidl:fuchsia.images",
"$fuchsia_sdk_root/fidl:fuchsia.intl",
"$fuchsia_sdk_root/fidl:fuchsia.io",
"$fuchsia_sdk_root/fidl:fuchsia.sys",
"$fuchsia_sdk_root/fidl:fuchsia.ui.app",
"$fuchsia_sdk_root/fidl:fuchsia.ui.scenic",
"$fuchsia_sdk_root/pkg:async-cpp",
"$fuchsia_sdk_root/pkg:async-default",
"$fuchsia_sdk_root/pkg:async-loop",
"$fuchsia_sdk_root/pkg:async-loop-cpp",
"$fuchsia_sdk_root/pkg:fdio",
"$fuchsia_sdk_root/pkg:fidl_cpp",
"$fuchsia_sdk_root/pkg:syslog",
"$fuchsia_sdk_root/pkg:trace",
"$fuchsia_sdk_root/pkg:trace-engine",
"$fuchsia_sdk_root/pkg:trace-provider-so",
"$fuchsia_sdk_root/pkg:vfs_cpp",
"$fuchsia_sdk_root/pkg:zx",
"//flutter/shell/platform/fuchsia/dart-pkg/fuchsia",
"//flutter/shell/platform/fuchsia/dart-pkg/zircon",
] + flutter_deps
}
# Things that explicitly being excluded:
# 1. Kernel snapshot framework mode.
# 2. Profiler symbols.
# Builds a flutter_runner
#
# Parameters:
#
# output_name (required):
# The name of the resulting binary.
#
# extra_deps (required):
# Any additional dependencies.
#
# product (required):
# Whether to link against a Product mode Dart VM.
#
# extra_defines (optional):
# Any additional preprocessor defines.
template("flutter_runner") {
assert(defined(invoker.output_name), "flutter_runner must define output_name")
assert(defined(invoker.extra_deps), "flutter_runner must define extra_deps")
assert(defined(invoker.product), "flutter_runner must define product")
invoker_output_name = invoker.output_name
extra_deps = invoker.extra_deps
extra_defines = []
if (defined(invoker.extra_defines)) {
extra_defines += invoker.extra_defines
}
executable(target_name) {
output_name = invoker_output_name
defines = extra_defines
sources = [ "main.cc" ]
deps = [
":flutter_runner_sources",
"$fuchsia_sdk_root/pkg:async-loop-cpp",
"$fuchsia_sdk_root/pkg:trace",
"$fuchsia_sdk_root/pkg:trace-provider-so",
] + extra_deps
# The flags below are needed so that Dart's CPU profiler can walk the
# C++ stack.
cflags = [ "-fno-omit-frame-pointer" ]
if (!invoker.product) {
# This flag is needed so that the call to dladdr() in Dart's native symbol
# resolver can report good symbol information for the CPU profiler.
ldflags = [ "-rdynamic" ]
}
}
}
flutter_runner("jit") {
output_name = "flutter_jit_runner"
product = false
......@@ -267,66 +414,36 @@ executable("flutter_runner_unittests") {
output_name = "flutter_runner_tests"
sources = [
"accessibility_bridge.cc",
"accessibility_bridge.h",
"accessibility_bridge_unittest.cc",
"component.cc",
"component.h",
"component_unittest.cc",
"flutter_runner_fakes.h",
"flutter_runner_product_configuration.cc",
"flutter_runner_product_configuration.h",
"fuchsia_intl.cc",
"fuchsia_intl.h",
"fuchsia_intl_unittest.cc",
"logging.h",
"loop.cc",
"loop.h",
"platform_view.cc",
"platform_view.h",
"platform_view_unittest.cc",
"runner.cc",
"runner.h",
"runner_unittest.cc",
"surface.cc",
"surface.h",
"task_observers.cc",
"task_observers.h",
"task_runner_adapter.cc",
"task_runner_adapter.h",
"tests/flutter_runner_product_configuration_unittests.cc",
"tests/vsync_recorder_unittests.cc",
"thread.cc",
"thread.h",
"vsync_recorder.cc",
"vsync_recorder.h",
"vsync_waiter.cc",
"vsync_waiter.h",
"vsync_waiter_unittests.cc",
]
# This is needed for //third_party/googletest for linking zircon symbols.
libs = [ "//fuchsia/sdk/$host_os/arch/$target_cpu/sysroot/lib/libzircon.so" ]
deps = [
":aot",
":flutter_runner_fixtures",
"//build/fuchsia/fidl:fuchsia.accessibility.semantics",
"//build/fuchsia/pkg:async-default",
"//build/fuchsia/pkg:async-loop-cpp",
"//build/fuchsia/pkg:async-loop-default",
"//build/fuchsia/pkg:scenic_cpp",
"//build/fuchsia/pkg:sys_cpp_testing",
"//flutter/common",
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_deps = [
"//flutter/flow:flow_fuchsia_legacy",
"//flutter/lib/ui:ui_fuchsia_legacy",
"//flutter/runtime:runtime_fuchsia_legacy",
"//flutter/shell/common:common_fuchsia_legacy",
"//flutter/shell/platform/fuchsia/runtime/dart/utils",
"//flutter/testing",
"//third_party/dart/runtime:libdart_jit",
"//third_party/dart/runtime/platform:libdart_platform_jit",
]
deps = [
":flutter_runner_fixtures",
":flutter_runner_sources",
"//build/fuchsia/pkg:sys_cpp_testing",
"//flutter/testing",
] + flutter_deps
}
executable("flutter_runner_tzdata_unittests") {
......@@ -334,34 +451,24 @@ executable("flutter_runner_tzdata_unittests") {
output_name = "flutter_runner_tzdata_tests"
sources = [
"runner.cc",
"runner.h",
"runner_tzdata_unittest.cc",
]
sources = [ "runner_tzdata_unittest.cc" ]
# This is needed for //third_party/googletest for linking zircon symbols.
libs = [ "//fuchsia/sdk/$host_os/arch/$target_cpu/sysroot/lib/libzircon.so" ]
deps = [
":aot",
":flutter_runner_fixtures",
"//build/fuchsia/fidl:fuchsia.accessibility.semantics",
"//build/fuchsia/pkg:async-loop-cpp",
"//build/fuchsia/pkg:async-loop-default",
"//build/fuchsia/pkg:scenic_cpp",
"//build/fuchsia/pkg:sys_cpp_testing",
"//flutter/flow:flow_fuchsia_legacy",
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_deps = [
"//flutter/lib/ui:ui_fuchsia_legacy",
"//flutter/runtime:runtime_fuchsia_legacy",
"//flutter/shell/common:common_fuchsia_legacy",
"//flutter/shell/platform/fuchsia/runtime/dart/utils",
"//flutter/testing",
"//third_party/dart/runtime:libdart_jit",
"//third_party/dart/runtime/platform:libdart_platform_jit",
"//third_party/icu",
"//third_party/skia",
]
deps = [
":flutter_runner_fixtures",
":flutter_runner_sources",
"//flutter/testing",
] + flutter_deps
}
executable("flutter_runner_scenic_unittests") {
......@@ -369,84 +476,27 @@ executable("flutter_runner_scenic_unittests") {
output_name = "flutter_runner_scenic_tests"
sources = [
"component.cc",
"component.h",
"compositor_context.cc",
"compositor_context.h",
"engine.cc",
"engine.h",
"fuchsia_intl.cc",
"fuchsia_intl.h",
"isolate_configurator.cc",
"isolate_configurator.h",
"logging.h",
"loop.cc",
"loop.h",
"platform_view.cc",
"platform_view.h",
"runner.cc",
"runner.h",
"session_connection.cc",
"session_connection.h",
"surface.cc",
"surface.h",
"task_observers.cc",
"task_observers.h",
"task_runner_adapter.cc",
"task_runner_adapter.h",
"tests/session_connection_unittests.cc",
"thread.cc",
"thread.h",
"unique_fdio_ns.h",
"vsync_recorder.cc",
"vsync_recorder.h",
"vsync_waiter.cc",
"vsync_waiter.h",
"vsync_waiter_unittests.cc",
"vulkan_surface.cc",
"vulkan_surface.h",
"vulkan_surface_pool.cc",
"vulkan_surface_pool.h",
"vulkan_surface_producer.cc",
"vulkan_surface_producer.h",
]
sources = [ "tests/session_connection_unittests.cc" ]
# This is needed for //third_party/googletest for linking zircon symbols.
libs = [ "//fuchsia/sdk/$host_os/arch/$target_cpu/sysroot/lib/libzircon.so" ]
deps = [
":flutter_runner_fixtures",
":jit",
"$fuchsia_sdk_root/fidl:fuchsia.ui.policy",
"$fuchsia_sdk_root/pkg:trace-provider-so",
"//build/fuchsia/fidl:fuchsia.accessibility.semantics",
"//build/fuchsia/pkg:async-default",
"//build/fuchsia/pkg:async-loop-cpp",
"//build/fuchsia/pkg:async-loop-default",
"//build/fuchsia/pkg:scenic_cpp",
"//build/fuchsia/pkg:sys_cpp_testing",
"//flutter/common",
"//flutter/flow:flow_fuchsia_legacy",
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_deps = [
"//flutter/lib/ui:ui_fuchsia_legacy",
"//flutter/runtime:runtime_fuchsia_legacy",
"//flutter/shell/common:common_fuchsia_legacy",
"//flutter/shell/platform/fuchsia/dart-pkg/fuchsia",
"//flutter/shell/platform/fuchsia/dart-pkg/zircon",
"//flutter/shell/platform/fuchsia/runtime/dart/utils",
"//flutter/testing",
"//flutter/vulkan",
"//third_party/dart/runtime:libdart_jit",
"//third_party/dart/runtime/platform:libdart_platform_jit",
"//third_party/icu",
"//third_party/skia",
]
public_deps = [ "//third_party/googletest:gtest" ]
deps = [
":flutter_runner_fixtures",
":flutter_runner_sources",
"$fuchsia_sdk_root/fidl:fuchsia.ui.policy",
"//flutter/testing",
] + flutter_deps
}
# When adding a new dep here, please also ensure the dep is added to
# testing/fuchsia/run_tests.sh and testing/fuchsia/test_fars
fuchsia_archive("flutter_runner_tests") {
testonly = true
......@@ -793,6 +843,8 @@ fuchsia_test_archive("ui_tests_next") {
resources += vulkan_icds
}
# When adding a new dep here, please also ensure the dep is added to
# testing/fuchsia/run_tests.sh and testing/fuchsia/test_fars
group("tests") {
testonly = true
......
......@@ -365,6 +365,12 @@ Application::Application(
// Controls whether category "skia" trace events are enabled.
settings_.trace_skia = true;
settings_.verbose_logging = true;
settings_.advisory_script_uri = debug_label_;
settings_.advisory_script_entrypoint = debug_label_;
settings_.icu_data_path = "";
settings_.assets_dir = application_assets_directory_.get();
......
......@@ -4,6 +4,8 @@
#include "compositor_context.h"
#include <vector>
#include "flutter/flow/layers/layer_tree.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
......@@ -11,30 +13,38 @@ namespace flutter_runner {
class ScopedFrame final : public flutter::CompositorContext::ScopedFrame {
public:
ScopedFrame(flutter::CompositorContext& context,
const SkMatrix& root_surface_transformation,
ScopedFrame(CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
flutter::ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled,
SessionConnection& session_connection)
: flutter::CompositorContext::ScopedFrame(
context,
session_connection.vulkan_surface_producer()->gr_context(),
nullptr,
view_embedder,
root_surface_transformation,
instrumentation_enabled,
true,
nullptr),
session_connection_(session_connection) {}
bool surface_supports_readback,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger,
SessionConnection& session_connection,
VulkanSurfaceProducer& surface_producer,
flutter::SceneUpdateContext& scene_update_context)
: flutter::CompositorContext::ScopedFrame(context,
surface_producer.gr_context(),
canvas,
view_embedder,
root_surface_transformation,
instrumentation_enabled,
surface_supports_readback,
raster_thread_merger),
session_connection_(session_connection),
surface_producer_(surface_producer),
scene_update_context_(scene_update_context) {}
private:
SessionConnection& session_connection_;
VulkanSurfaceProducer& surface_producer_;
flutter::SceneUpdateContext& scene_update_context_;
flutter::RasterStatus Raster(flutter::LayerTree& layer_tree,
bool ignore_raster_cache) override {
if (!session_connection_.has_metrics()) {
return flutter::RasterStatus::kSuccess;
}
std::vector<flutter::SceneUpdateContext::PaintTask> frame_paint_tasks;
std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
{
// Preroll the Flutter layer tree. This allows Flutter to perform
......@@ -47,15 +57,80 @@ class ScopedFrame final : public flutter::CompositorContext::ScopedFrame {
// Traverse the Flutter layer tree so that the necessary session ops to
// represent the frame are enqueued in the underlying session.
TRACE_EVENT0("flutter", "UpdateScene");
layer_tree.UpdateScene(session_connection_.scene_update_context(),
session_connection_.root_node());
layer_tree.UpdateScene(scene_update_context_);
}
{
// Flush all pending session ops.
// Flush all pending session ops: create surfaces and enqueue session
// Image ops for the frame's paint tasks, then Present.
TRACE_EVENT0("flutter", "SessionPresent");
frame_paint_tasks = scene_update_context_.GetPaintTasks();
for (auto& task : frame_paint_tasks) {
SkISize physical_size =
SkISize::Make(layer_tree.device_pixel_ratio() * task.scale_x *
task.paint_bounds.width(),
layer_tree.device_pixel_ratio() * task.scale_y *
task.paint_bounds.height());
if (physical_size.width() == 0 || physical_size.height() == 0) {
frame_surfaces.emplace_back(nullptr);
continue;
}
std::unique_ptr<SurfaceProducerSurface> surface =
surface_producer_.ProduceSurface(physical_size);
if (!surface) {
FML_LOG(ERROR)
<< "Could not acquire a surface from the surface producer "
"of size: "
<< physical_size.width() << "x" << physical_size.height();
} else {
task.material.SetTexture(*(surface->GetImage()));
}
frame_surfaces.emplace_back(std::move(surface));
}
session_connection_.Present();
}
session_connection_.Present(this);
{
// Execute paint tasks in parallel with Scenic's side of the Present, then
// signal fences.
TRACE_EVENT0("flutter", "ExecutePaintTasks");
size_t surface_index = 0;
for (auto& task : frame_paint_tasks) {
std::unique_ptr<SurfaceProducerSurface>& task_surface =
frame_surfaces[surface_index++];
if (!task_surface) {
continue;
}
SkCanvas* canvas = task_surface->GetSkiaSurface()->getCanvas();
flutter::Layer::PaintContext paint_context = {
canvas,
canvas,
gr_context(),
nullptr,
context().raster_time(),
context().ui_time(),
context().texture_registry(),
&context().raster_cache(),
false,
layer_tree.device_pixel_ratio()};
canvas->restoreToCount(1);
canvas->save();
canvas->clear(task.background_color);
canvas->scale(layer_tree.device_pixel_ratio() * task.scale_x,
layer_tree.device_pixel_ratio() * task.scale_y);
canvas->translate(-task.paint_bounds.left(), -task.paint_bounds.top());
for (flutter::Layer* layer : task.layers) {
layer->Paint(paint_context);
}
}
// Tell the surface producer that a present has occurred so it can perform
// book-keeping on buffer caches.
surface_producer_.OnSurfacesPresented(std::move(frame_surfaces));
}
return flutter::RasterStatus::kSuccess;
......@@ -65,51 +140,14 @@ class ScopedFrame final : public flutter::CompositorContext::ScopedFrame {
};
CompositorContext::CompositorContext(
std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
fidl::InterfaceHandle<fuchsia::ui::scenic::Session> session,
fml::closure session_error_callback,
zx_handle_t vsync_event_handle)
: debug_label_(std::move(debug_label)),
session_connection_(
debug_label_,
std::move(view_token),
std::move(view_ref_pair),
std::move(session),
session_error_callback,
[](auto) {},
vsync_event_handle) {}
void CompositorContext::OnSessionMetricsDidChange(
const fuchsia::ui::gfx::Metrics& metrics) {
session_connection_.set_metrics(metrics);
}
SessionConnection& session_connection,
VulkanSurfaceProducer& surface_producer,
flutter::SceneUpdateContext& scene_update_context)
: session_connection_(session_connection),
surface_producer_(surface_producer),
scene_update_context_(scene_update_context) {}
void CompositorContext::OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor) {
session_connection_.OnSessionSizeChangeHint(width_change_factor,
height_change_factor);
}
void CompositorContext::OnWireframeEnabled(bool enabled) {
session_connection_.set_enable_wireframe(enabled);
}
void CompositorContext::OnCreateView(int64_t view_id,
bool hit_testable,
bool focusable) {
session_connection_.scene_update_context().CreateView(view_id, hit_testable,
focusable);
}
void CompositorContext::OnDestroyView(int64_t view_id) {
session_connection_.scene_update_context().DestroyView(view_id);
}
CompositorContext::~CompositorContext() {
OnGrContextDestroyed();
}
CompositorContext::~CompositorContext() = default;
std::unique_ptr<flutter::CompositorContext::ScopedFrame>
CompositorContext::AcquireFrame(
......@@ -120,16 +158,10 @@ CompositorContext::AcquireFrame(
bool instrumentation_enabled,
bool surface_supports_readback,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
// TODO: The AcquireFrame interface is too broad and must be refactored to get
// rid of the context and canvas arguments as those seem to be only used for
// colorspace correctness purposes on the mobile shells.
return std::make_unique<flutter_runner::ScopedFrame>(
*this, //
root_surface_transformation, //
view_embedder,
instrumentation_enabled, //
session_connection_ //
);
*this, gr_context, canvas, view_embedder, root_surface_transformation,
instrumentation_enabled, surface_supports_readback, raster_thread_merger,
session_connection_, surface_producer_, scene_update_context_);
}
} // namespace flutter_runner
......@@ -5,15 +5,15 @@
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_COMPOSITOR_CONTEXT_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_COMPOSITOR_CONTEXT_H_
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <memory>
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h"
#include "session_connection.h"
#include "vulkan_surface_producer.h"
namespace flutter_runner {
......@@ -21,31 +21,16 @@ namespace flutter_runner {
// Fuchsia.
class CompositorContext final : public flutter::CompositorContext {
public:
CompositorContext(std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
fidl::InterfaceHandle<fuchsia::ui::scenic::Session> session,
fml::closure session_error_callback,
zx_handle_t vsync_event_handle);
CompositorContext(SessionConnection& session_connection,
VulkanSurfaceProducer& surface_producer,
flutter::SceneUpdateContext& scene_update_context);
~CompositorContext() override;
void OnSessionMetricsDidChange(const fuchsia::ui::gfx::Metrics& metrics);
void OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor);
void OnWireframeEnabled(bool enabled);
void OnCreateView(int64_t view_id, bool hit_testable, bool focusable);
void OnDestroyView(int64_t view_id);
flutter::ExternalViewEmbedder* GetViewEmbedder() {
return &session_connection_.scene_update_context();
}
private:
const std::string debug_label_;
scenic::ViewRefPair view_ref_pair_;
SessionConnection session_connection_;
SessionConnection& session_connection_;
VulkanSurfaceProducer& surface_producer_;
flutter::SceneUpdateContext& scene_update_context_;
// |flutter::CompositorContext|
std::unique_ptr<ScopedFrame> AcquireFrame(
......
......@@ -7,9 +7,6 @@
#include <lib/async/cpp/task.h>
#include <zircon/status.h>
#include <sstream>
#include "compositor_context.h"
#include "flutter/common/task_runners.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/synchronization/waitable_event.h"
......@@ -17,18 +14,21 @@
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/run_configuration.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "../runtime/dart/utils/files.h"
#include "compositor_context.h"
#include "flutter_runner_product_configuration.h"
#include "fuchsia_intl.h"
#include "platform_view.h"
#include "runtime/dart/utils/files.h"
#include "task_runner_adapter.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "thread.h"
namespace flutter_runner {
namespace {
static void UpdateNativeThreadLabelNames(const std::string& label,
const flutter::TaskRunners& runners) {
void UpdateNativeThreadLabelNames(const std::string& label,
const flutter::TaskRunners& runners) {
auto set_thread_name = [](fml::RefPtr<fml::TaskRunner> runner,
std::string prefix, std::string suffix) {
if (!runner) {
......@@ -44,13 +44,15 @@ static void UpdateNativeThreadLabelNames(const std::string& label,
set_thread_name(runners.GetIOTaskRunner(), label, ".io");
}
static fml::RefPtr<flutter::PlatformMessage> MakeLocalizationPlatformMessage(
fml::RefPtr<flutter::PlatformMessage> MakeLocalizationPlatformMessage(
const fuchsia::intl::Profile& intl_profile) {
return fml::MakeRefCounted<flutter::PlatformMessage>(
"flutter/localization", MakeLocalizationPlatformMessageData(intl_profile),
nullptr);
}
} // namespace
Engine::Engine(Delegate& delegate,
std::string thread_label,
std::shared_ptr<sys::ServiceDirectory> svc,
......@@ -64,28 +66,70 @@ Engine::Engine(Delegate& delegate,
FlutterRunnerProductConfiguration product_config)
: delegate_(delegate),
thread_label_(std::move(thread_label)),
settings_(std::move(settings)),
weak_factory_(this) {
if (zx::event::create(0, &vsync_event_) != ZX_OK) {
FML_DLOG(ERROR) << "Could not create the vsync event.";
return;
}
// Launch the threads that will be used to run the shell. These threads will
// be joined in the destructor.
for (auto& thread : threads_) {
thread.reset(new Thread());
}
// Get the task runners from the managed threads. The current thread will be
// used as the "platform" thread.
const flutter::TaskRunners task_runners(
thread_label_, // Dart thread labels
CreateFMLTaskRunner(async_get_default_dispatcher()), // platform
CreateFMLTaskRunner(threads_[0].dispatcher()), // raster
CreateFMLTaskRunner(threads_[1].dispatcher()), // ui
CreateFMLTaskRunner(threads_[2].dispatcher()) // io
);
UpdateNativeThreadLabelNames(thread_label_, task_runners);
// Set up the session connection.
// Connect to Scenic.
auto scenic = svc->Connect<fuchsia::ui::scenic::Scenic>();
fidl::InterfaceHandle<fuchsia::ui::scenic::Session> session;
fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> session_listener;
auto session_listener_request = session_listener.NewRequest();
scenic->CreateSession(session.NewRequest(), session_listener.Bind());
// Grab the parent environment services. The platform view may want to access
// some of these services.
// Make clones of the `ViewRef` before sending it down to Scenic.
fuchsia::ui::views::ViewRef platform_view_ref, isolate_view_ref;
view_ref_pair.view_ref.Clone(&platform_view_ref);
view_ref_pair.view_ref.Clone(&isolate_view_ref);
// Session is terminated on the raster thread, but we must terminate ourselves
// on the platform thread.
//
// This handles the fidl error callback when the Session connection is
// broken. The SessionListener interface also has an OnError method, which is
// invoked on the platform thread (in PlatformView).
fml::closure session_error_callback = [dispatcher =
async_get_default_dispatcher(),
weak = weak_factory_.GetWeakPtr()]() {
async::PostTask(dispatcher, [weak]() {
if (weak) {
weak->Terminate();
}
});
};
// Set up the session connection and other Scenic helpers on the raster
// thread.
task_runners.GetRasterTaskRunner()->PostTask(fml::MakeCopyable(
[this, session = std::move(session),
session_error_callback = std::move(session_error_callback),
view_token = std::move(view_token),
view_ref_pair = std::move(view_ref_pair),
vsync_handle = vsync_event_.get()]() mutable {
session_connection_.emplace(
thread_label_, std::move(session),
std::move(session_error_callback), [](auto) {}, vsync_handle);
surface_producer_.emplace(session_connection_->get());
scene_update_context_.emplace(thread_label_, std::move(view_token),
std::move(view_ref_pair),
session_connection_.value());
}));
// Grab the parent environment services. The platform view may want to
// access some of these services.
fuchsia::sys::EnvironmentPtr environment;
svc->Connect(environment.NewRequest());
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider>
......@@ -93,23 +137,15 @@ Engine::Engine(Delegate& delegate,
environment->GetServices(parent_environment_service_provider.NewRequest());
environment.Unbind();
// We need to manually schedule a frame when the session metrics change.
OnMetricsUpdate on_session_metrics_change_callback = std::bind(
&Engine::OnSessionMetricsDidChange, this, std::placeholders::_1);
OnSizeChangeHint on_session_size_change_hint_callback =
std::bind(&Engine::OnSessionSizeChangeHint, this, std::placeholders::_1,
std::placeholders::_2);
OnEnableWireframe on_enable_wireframe_callback = std::bind(
&Engine::OnDebugWireframeSettingsChanged, this, std::placeholders::_1);
&Engine::DebugWireframeSettingsChanged, this, std::placeholders::_1);
flutter_runner::OnCreateView on_create_view_callback =
std::bind(&Engine::OnCreateView, this, std::placeholders::_1,
OnCreateView on_create_view_callback =
std::bind(&Engine::CreateView, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
flutter_runner::OnDestroyView on_destroy_view_callback =
std::bind(&Engine::OnDestroyView, this, std::placeholders::_1);
OnDestroyView on_destroy_view_callback =
std::bind(&Engine::DestroyView, this, std::placeholders::_1);
OnGetViewEmbedder on_get_view_embedder_callback =
std::bind(&Engine::GetViewEmbedder, this);
......@@ -127,10 +163,6 @@ Engine::Engine(Delegate& delegate,
});
};
fuchsia::ui::views::ViewRef platform_view_ref, isolate_view_ref;
view_ref_pair.view_ref.Clone(&platform_view_ref);
view_ref_pair.view_ref.Clone(&isolate_view_ref);
// Setup the callback that will instantiate the platform view.
flutter::Shell::CreateCallback<flutter::PlatformView>
on_create_platform_view = fml::MakeCopyable(
......@@ -141,10 +173,6 @@ Engine::Engine(Delegate& delegate,
session_listener_request = std::move(session_listener_request),
on_session_listener_error_callback =
std::move(on_session_listener_error_callback),
on_session_metrics_change_callback =
std::move(on_session_metrics_change_callback),
on_session_size_change_hint_callback =
std::move(on_session_size_change_hint_callback),
on_enable_wireframe_callback =
std::move(on_enable_wireframe_callback),
on_create_view_callback = std::move(on_create_view_callback),
......@@ -162,8 +190,6 @@ Engine::Engine(Delegate& delegate,
std::move(parent_environment_service_provider), // services
std::move(session_listener_request), // session listener
std::move(on_session_listener_error_callback),
std::move(on_session_metrics_change_callback),
std::move(on_session_size_change_hint_callback),
std::move(on_enable_wireframe_callback),
std::move(on_create_view_callback),
std::move(on_destroy_view_callback),
......@@ -172,53 +198,17 @@ Engine::Engine(Delegate& delegate,
product_config);
});
// Session can be terminated on the raster thread, but we must terminate
// ourselves on the platform thread.
//
// This handles the fidl error callback when the Session connection is
// broken. The SessionListener interface also has an OnError method, which is
// invoked on the platform thread (in PlatformView).
fml::closure on_session_error_callback =
[dispatcher = async_get_default_dispatcher(),
weak = weak_factory_.GetWeakPtr()]() {
async::PostTask(dispatcher, [weak]() {
if (weak) {
weak->Terminate();
}
});
};
// Get the task runners from the managed threads. The current thread will be
// used as the "platform" thread.
const flutter::TaskRunners task_runners(
thread_label_, // Dart thread labels
CreateFMLTaskRunner(async_get_default_dispatcher()), // platform
CreateFMLTaskRunner(threads_[0]->dispatcher()), // raster
CreateFMLTaskRunner(threads_[1]->dispatcher()), // ui
CreateFMLTaskRunner(threads_[2]->dispatcher()) // io
);
// Setup the callback that will instantiate the rasterizer.
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
fml::MakeCopyable([thread_label = thread_label_, //
view_token = std::move(view_token), //
view_ref_pair = std::move(view_ref_pair), //
session = std::move(session), //
on_session_error_callback, //
vsync_event = vsync_event_.get() //
](flutter::Shell& shell) mutable {
std::unique_ptr<flutter_runner::CompositorContext> compositor_context;
{
TRACE_DURATION("flutter", "CreateCompositorContext");
compositor_context =
std::make_unique<flutter_runner::CompositorContext>(
thread_label, // debug label
std::move(view_token), // scenic view we attach our tree to
std::move(view_ref_pair), // scenic view ref/view ref control
std::move(session), // scenic session
on_session_error_callback, // session did encounter error
vsync_event); // vsync event handle
}
fml::MakeCopyable([this](flutter::Shell& shell) mutable {
FML_DCHECK(session_connection_);
FML_DCHECK(surface_producer_);
FML_DCHECK(scene_update_context_);
std::unique_ptr<flutter_runner::CompositorContext> compositor_context =
std::make_unique<flutter_runner::CompositorContext>(
session_connection_.value(), surface_producer_.value(),
scene_update_context_.value());
return std::make_unique<flutter::Rasterizer>(
/*task_runners=*/shell.GetTaskRunners(),
......@@ -226,18 +216,9 @@ Engine::Engine(Delegate& delegate,
/*is_gpu_disabled_sync_switch=*/shell.GetIsGpuDisabledSyncSwitch());
});
UpdateNativeThreadLabelNames(thread_label_, task_runners);
settings_.verbose_logging = true;
settings_.advisory_script_uri = thread_label_;
settings_.advisory_script_entrypoint = thread_label_;
settings_.root_isolate_create_callback =
settings.root_isolate_create_callback =
std::bind(&Engine::OnMainIsolateStart, this);
settings_.root_isolate_shutdown_callback =
settings.root_isolate_shutdown_callback =
std::bind([weak = weak_factory_.GetWeakPtr(),
runner = task_runners.GetPlatformTaskRunner()]() {
runner->PostTask([weak = std::move(weak)] {
......@@ -247,7 +228,7 @@ Engine::Engine(Delegate& delegate,
});
});
auto vm = flutter::DartVMRef::Create(settings_);
auto vm = flutter::DartVMRef::Create(settings);
if (!isolate_snapshot) {
isolate_snapshot = vm->GetVMData()->GetIsolateSnapshot();
......@@ -256,13 +237,13 @@ Engine::Engine(Delegate& delegate,
{
TRACE_EVENT0("flutter", "CreateShell");
shell_ = flutter::Shell::Create(
task_runners, // host task runners
flutter::PlatformData(), // default window data
settings_, // shell launch settings
std::move(isolate_snapshot), // isolate snapshot
on_create_platform_view, // platform view create callback
on_create_rasterizer, // rasterizer create callback
std::move(vm) // vm reference
std::move(task_runners), // host task runners
flutter::PlatformData(), // default window data
std::move(settings), // shell launch settings
std::move(isolate_snapshot), // isolate snapshot
std::move(on_create_platform_view), // platform view create callback
std::move(on_create_rasterizer), // rasterizer create callback
std::move(vm) // vm reference
);
}
......@@ -339,7 +320,7 @@ Engine::Engine(Delegate& delegate,
// Launch the engine in the appropriate configuration.
auto run_configuration = flutter::RunConfiguration::InferFromSettings(
settings_, task_runners.GetIOTaskRunner());
shell_->GetSettings(), shell_->GetTaskRunners().GetIOTaskRunner());
auto on_run_failure = [weak = weak_factory_.GetWeakPtr()]() {
// The engine could have been killed by the caller right after the
......@@ -376,11 +357,11 @@ Engine::Engine(Delegate& delegate,
Engine::~Engine() {
shell_.reset();
for (const auto& thread : threads_) {
thread->Quit();
for (auto& thread : threads_) {
thread.Quit();
}
for (const auto& thread : threads_) {
thread->Join();
for (auto& thread : threads_) {
thread.Join();
}
}
......@@ -485,105 +466,41 @@ void Engine::Terminate() {
// collected this object.
}
void Engine::OnSessionMetricsDidChange(
const fuchsia::ui::gfx::Metrics& metrics) {
if (!shell_) {
return;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[rasterizer = shell_->GetRasterizer(), metrics]() {
if (rasterizer) {
auto compositor_context =
reinterpret_cast<flutter_runner::CompositorContext*>(
rasterizer->compositor_context());
compositor_context->OnSessionMetricsDidChange(metrics);
}
});
}
void Engine::OnDebugWireframeSettingsChanged(bool enabled) {
if (!shell_) {
void Engine::DebugWireframeSettingsChanged(bool enabled) {
if (!shell_ || !scene_update_context_) {
return;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[rasterizer = shell_->GetRasterizer(), enabled]() {
if (rasterizer) {
auto compositor_context =
reinterpret_cast<flutter_runner::CompositorContext*>(
rasterizer->compositor_context());
compositor_context->OnWireframeEnabled(enabled);
}
});
[this, enabled]() { scene_update_context_->EnableWireframe(enabled); });
}
void Engine::OnCreateView(int64_t view_id, bool hit_testable, bool focusable) {
if (!shell_) {
void Engine::CreateView(int64_t view_id, bool hit_testable, bool focusable) {
if (!shell_ || !scene_update_context_) {
return;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[rasterizer = shell_->GetRasterizer(), view_id, hit_testable,
focusable]() {
if (rasterizer) {
auto compositor_context =
reinterpret_cast<flutter_runner::CompositorContext*>(
rasterizer->compositor_context());
compositor_context->OnCreateView(view_id, hit_testable, focusable);
}
[this, view_id, hit_testable, focusable]() {
scene_update_context_->CreateView(view_id, hit_testable, focusable);
});
}
void Engine::OnDestroyView(int64_t view_id) {
if (!shell_) {
void Engine::DestroyView(int64_t view_id) {
if (!shell_ || !scene_update_context_) {
return;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[rasterizer = shell_->GetRasterizer(), view_id]() {
if (rasterizer) {
auto compositor_context =
reinterpret_cast<flutter_runner::CompositorContext*>(
rasterizer->compositor_context());
compositor_context->OnDestroyView(view_id);
}
});
[this, view_id]() { scene_update_context_->DestroyView(view_id); });
}
flutter::ExternalViewEmbedder* Engine::GetViewEmbedder() {
// GetEmbedder should be called only after rasterizer is created.
FML_DCHECK(shell_);
FML_DCHECK(shell_->GetRasterizer());
auto rasterizer = shell_->GetRasterizer();
auto compositor_context =
reinterpret_cast<flutter_runner::CompositorContext*>(
rasterizer->compositor_context());
flutter::ExternalViewEmbedder* view_embedder =
compositor_context->GetViewEmbedder();
return view_embedder;
}
void Engine::OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor) {
if (!shell_) {
return;
if (!scene_update_context_) {
return nullptr;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[rasterizer = shell_->GetRasterizer(), width_change_factor,
height_change_factor]() {
if (rasterizer) {
auto compositor_context = reinterpret_cast<CompositorContext*>(
rasterizer->compositor_context());
compositor_context->OnSessionSizeChangeHint(width_change_factor,
height_change_factor);
}
});
return &scene_update_context_.value();
}
#if !defined(DART_PRODUCT)
......
......@@ -15,11 +15,15 @@
#include <lib/zx/event.h>
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/common/shell.h"
#include "flutter_runner_product_configuration.h"
#include "isolate_configurator.h"
#include "session_connection.h"
#include "thread.h"
#include "vulkan_surface_producer.h"
namespace flutter_runner {
......@@ -55,15 +59,22 @@ class Engine final {
private:
Delegate& delegate_;
const std::string thread_label_;
flutter::Settings settings_;
std::array<std::unique_ptr<Thread>, 3> threads_;
std::array<Thread, 3> threads_;
std::optional<SessionConnection> session_connection_;
std::optional<VulkanSurfaceProducer> surface_producer_;
std::optional<flutter::SceneUpdateContext> scene_update_context_;
std::unique_ptr<IsolateConfigurator> isolate_configurator_;
std::unique_ptr<flutter::Shell> shell_;
fuchsia::intl::PropertyProviderPtr intl_property_provider_;
zx::event vsync_event_;
fml::WeakPtrFactory<Engine> weak_factory_;
// A stub for the FIDL protocol fuchsia.intl.PropertyProvider.
fuchsia::intl::PropertyProviderPtr intl_property_provider_;
void OnMainIsolateStart();
......@@ -71,15 +82,9 @@ class Engine final {
void Terminate();
void OnSessionMetricsDidChange(const fuchsia::ui::gfx::Metrics& metrics);
void OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor);
void OnDebugWireframeSettingsChanged(bool enabled);
void OnCreateView(int64_t view_id, bool hit_testable, bool focusable);
void OnDestroyView(int64_t view_id);
void DebugWireframeSettingsChanged(bool enabled);
void CreateView(int64_t view_id, bool hit_testable, bool focusable);
void DestroyView(int64_t view_id);
flutter::ExternalViewEmbedder* GetViewEmbedder();
......
# 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.
assert(is_fuchsia)
import("//build/fuchsia/sdk.gni")
# Builds a flutter_runner
#
# Parameters:
#
# output_name (required):
# The name of the resulting binary.
#
# extra_deps (required):
# Any additional dependencies.
#
# product (required):
# Whether to link against a Product mode Dart VM.
#
# extra_defines (optional):
# Any additional preprocessor defines.
template("flutter_runner") {
assert(defined(invoker.output_name), "flutter_runner must define output_name")
assert(defined(invoker.extra_deps), "flutter_runner must define extra_deps")
assert(defined(invoker.product), "flutter_runner must define product")
invoker_output_name = invoker.output_name
extra_deps = invoker.extra_deps
extra_defines = []
if (defined(invoker.extra_defines)) {
extra_defines += invoker.extra_defines
}
executable(target_name) {
output_name = invoker_output_name
defines = extra_defines
libs = []
sources = [
"accessibility_bridge.cc",
"accessibility_bridge.h",
"component.cc",
"component.h",
"compositor_context.cc",
"compositor_context.h",
"engine.cc",
"engine.h",
"flutter_runner_product_configuration.cc",
"flutter_runner_product_configuration.h",
"fuchsia_intl.cc",
"fuchsia_intl.h",
"isolate_configurator.cc",
"isolate_configurator.h",
"logging.h",
"loop.cc",
"loop.h",
"main.cc",
"platform_view.cc",
"platform_view.h",
"runner.cc",
"runner.h",
"session_connection.cc",
"session_connection.h",
"surface.cc",
"surface.h",
"task_observers.cc",
"task_observers.h",
"task_runner_adapter.cc",
"task_runner_adapter.h",
"thread.cc",
"thread.h",
"unique_fdio_ns.h",
"vsync_recorder.cc",
"vsync_recorder.h",
"vsync_waiter.cc",
"vsync_waiter.h",
"vulkan_surface.cc",
"vulkan_surface.h",
"vulkan_surface_pool.cc",
"vulkan_surface_pool.h",
"vulkan_surface_producer.cc",
"vulkan_surface_producer.h",
]
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_deps = [
"../flutter:fuchsia_legacy_gpu_configuration",
"//flutter/assets",
"//flutter/common",
"//flutter/flow:flow_fuchsia_legacy",
"//flutter/fml",
"//flutter/lib/ui:ui_fuchsia_legacy",
"//flutter/runtime:runtime_fuchsia_legacy",
"//flutter/shell/common:common_fuchsia_legacy",
"//flutter/vulkan",
]
_fuchsia_platform = "//flutter/shell/platform/fuchsia"
# TODO(kaushikiska) evaluate if all of these are needed.
fuchsia_deps = [
"${_fuchsia_platform}/dart-pkg/fuchsia",
"${_fuchsia_platform}/dart-pkg/zircon",
"${_fuchsia_platform}/runtime/dart/utils",
]
deps = [
"$fuchsia_sdk_root/fidl:fuchsia.accessibility.semantics",
"$fuchsia_sdk_root/fidl:fuchsia.fonts",
"$fuchsia_sdk_root/fidl:fuchsia.images",
"$fuchsia_sdk_root/fidl:fuchsia.intl",
"$fuchsia_sdk_root/fidl:fuchsia.io",
"$fuchsia_sdk_root/fidl:fuchsia.sys",
"$fuchsia_sdk_root/fidl:fuchsia.ui.app",
"$fuchsia_sdk_root/fidl:fuchsia.ui.scenic",
"$fuchsia_sdk_root/pkg:async-cpp",
"$fuchsia_sdk_root/pkg:async-default",
"$fuchsia_sdk_root/pkg:async-loop",
"$fuchsia_sdk_root/pkg:async-loop-cpp",
"$fuchsia_sdk_root/pkg:fdio",
"$fuchsia_sdk_root/pkg:fidl_cpp",
"$fuchsia_sdk_root/pkg:scenic_cpp",
"$fuchsia_sdk_root/pkg:sys_cpp",
"$fuchsia_sdk_root/pkg:syslog",
"$fuchsia_sdk_root/pkg:trace",
"$fuchsia_sdk_root/pkg:trace-engine",
"$fuchsia_sdk_root/pkg:trace-provider-so",
"$fuchsia_sdk_root/pkg:vfs_cpp",
"$fuchsia_sdk_root/pkg:zx",
"//third_party/skia",
"//flutter/third_party/tonic",
] + fuchsia_deps + flutter_deps + extra_deps
# The flags below are needed so that Dart's CPU profiler can walk the
# C++ stack.
cflags = [ "-fno-omit-frame-pointer" ]
if (!invoker.product) {
# This flag is needed so that the call to dladdr() in Dart's native symbol
# resolver can report good symbol information for the CPU profiler.
ldflags = [ "-rdynamic" ]
}
}
}
......@@ -6,6 +6,7 @@
#include "platform_view.h"
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <sstream>
#include "flutter/fml/logging.h"
......@@ -22,41 +23,6 @@
namespace flutter_runner {
namespace {
inline fuchsia::ui::gfx::vec3 Add(const fuchsia::ui::gfx::vec3& a,
const fuchsia::ui::gfx::vec3& b) {
return {.x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z};
}
inline fuchsia::ui::gfx::vec3 Subtract(const fuchsia::ui::gfx::vec3& a,
const fuchsia::ui::gfx::vec3& b) {
return {.x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z};
}
inline fuchsia::ui::gfx::BoundingBox InsetBy(
const fuchsia::ui::gfx::BoundingBox& box,
const fuchsia::ui::gfx::vec3& inset_from_min,
const fuchsia::ui::gfx::vec3& inset_from_max) {
return {.min = Add(box.min, inset_from_min),
.max = Subtract(box.max, inset_from_max)};
}
inline fuchsia::ui::gfx::BoundingBox ViewPropertiesLayoutBox(
const fuchsia::ui::gfx::ViewProperties& view_properties) {
return InsetBy(view_properties.bounding_box, view_properties.inset_from_min,
view_properties.inset_from_max);
}
inline fuchsia::ui::gfx::vec3 Max(const fuchsia::ui::gfx::vec3& v,
float min_val) {
return {.x = std::max(v.x, min_val),
.y = std::max(v.y, min_val),
.z = std::max(v.z, min_val)};
}
} // end namespace
static constexpr char kFlutterPlatformChannel[] = "flutter/platform";
static constexpr char kTextInputChannel[] = "flutter/textinput";
static constexpr char kKeyEventChannel[] = "flutter/keyevent";
......@@ -89,8 +55,6 @@ PlatformView::PlatformView(
fidl::InterfaceRequest<fuchsia::ui::scenic::SessionListener>
session_listener_request,
fit::closure session_listener_error_callback,
OnMetricsUpdate session_metrics_did_change_callback,
OnSizeChangeHint session_size_change_hint_callback,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnDestroyView on_destroy_view_callback,
......@@ -103,8 +67,6 @@ PlatformView::PlatformView(
session_listener_binding_(this, std::move(session_listener_request)),
session_listener_error_callback_(
std::move(session_listener_error_callback)),
metrics_changed_callback_(std::move(session_metrics_did_change_callback)),
size_change_hint_callback_(std::move(session_size_change_hint_callback)),
wireframe_enabled_callback_(std::move(wireframe_enabled_callback)),
on_create_view_callback_(std::move(on_create_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)),
......@@ -152,64 +114,6 @@ void PlatformView::RegisterPlatformMessageHandlers() {
this, std::placeholders::_1);
}
void PlatformView::OnPropertiesChanged(
const fuchsia::ui::gfx::ViewProperties& view_properties) {
fuchsia::ui::gfx::BoundingBox layout_box =
ViewPropertiesLayoutBox(view_properties);
fuchsia::ui::gfx::vec3 logical_size =
Max(Subtract(layout_box.max, layout_box.min), 0.f);
metrics_.size.width = logical_size.x;
metrics_.size.height = logical_size.y;
metrics_.size.depth = logical_size.z;
metrics_.padding.left = view_properties.inset_from_min.x;
metrics_.padding.top = view_properties.inset_from_min.y;
metrics_.padding.front = view_properties.inset_from_min.z;
metrics_.padding.right = view_properties.inset_from_max.x;
metrics_.padding.bottom = view_properties.inset_from_max.y;
metrics_.padding.back = view_properties.inset_from_max.z;
FlushViewportMetrics();
}
// TODO(SCN-975): Re-enable.
// void PlatformView::ConnectSemanticsProvider(
// fuchsia::ui::viewsv1token::ViewToken token) {
// semantics_bridge_.SetupEnvironment(
// token.value, parent_environment_service_provider_.get());
// }
void PlatformView::UpdateViewportMetrics(
const fuchsia::ui::gfx::Metrics& metrics) {
metrics_.scale = metrics.scale_x;
metrics_.scale_z = metrics.scale_z;
FlushViewportMetrics();
}
void PlatformView::FlushViewportMetrics() {
const auto scale = metrics_.scale;
const auto scale_z = metrics_.scale_z;
SetViewportMetrics({
scale, // device_pixel_ratio
metrics_.size.width * scale, // physical_width
metrics_.size.height * scale, // physical_height
metrics_.size.depth * scale_z, // physical_depth
metrics_.padding.top * scale, // physical_padding_top
metrics_.padding.right * scale, // physical_padding_right
metrics_.padding.bottom * scale, // physical_padding_bottom
metrics_.padding.left * scale, // physical_padding_left
metrics_.view_inset.front * scale_z, // physical_view_inset_front
metrics_.view_inset.back * scale_z, // physical_view_inset_back
metrics_.view_inset.top * scale, // physical_view_inset_top
metrics_.view_inset.right * scale, // physical_view_inset_right
metrics_.view_inset.bottom * scale, // physical_view_inset_bottom
metrics_.view_inset.left * scale // physical_view_inset_left
});
}
// |fuchsia::ui::input::InputMethodEditorClient|
void PlatformView::DidUpdateState(
fuchsia::ui::input::TextInputState state,
......@@ -302,27 +206,40 @@ void PlatformView::OnScenicError(std::string error) {
void PlatformView::OnScenicEvent(
std::vector<fuchsia::ui::scenic::Event> events) {
TRACE_EVENT0("flutter", "PlatformView::OnScenicEvent");
bool should_update_metrics = false;
for (const auto& event : events) {
switch (event.Which()) {
case fuchsia::ui::scenic::Event::Tag::kGfx:
switch (event.gfx().Which()) {
case fuchsia::ui::gfx::Event::Tag::kMetrics: {
if (!fidl::Equals(event.gfx().metrics().metrics, scenic_metrics_)) {
scenic_metrics_ = std::move(event.gfx().metrics().metrics);
metrics_changed_callback_(scenic_metrics_);
UpdateViewportMetrics(scenic_metrics_);
const fuchsia::ui::gfx::Metrics& metrics =
event.gfx().metrics().metrics;
const float new_view_pixel_ratio = metrics.scale_x;
// Avoid metrics update when possible -- it is computationally
// expensive.
if (view_pixel_ratio_ != new_view_pixel_ratio) {
view_pixel_ratio_ = new_view_pixel_ratio;
should_update_metrics = true;
}
break;
}
case fuchsia::ui::gfx::Event::Tag::kSizeChangeHint: {
size_change_hint_callback_(
event.gfx().size_change_hint().width_change_factor,
event.gfx().size_change_hint().height_change_factor);
break;
}
case fuchsia::ui::gfx::Event::Tag::kViewPropertiesChanged: {
OnPropertiesChanged(
std::move(event.gfx().view_properties_changed().properties));
const fuchsia::ui::gfx::BoundingBox& bounding_box =
event.gfx().view_properties_changed().properties.bounding_box;
const float new_view_width =
std::max(bounding_box.max.x - bounding_box.min.x, 0.0f);
const float new_view_height =
std::max(bounding_box.max.y - bounding_box.min.y, 0.0f);
// Avoid metrics update when possible -- it is computationally
// expensive.
if (view_width_ != new_view_width ||
view_height_ != new_view_width) {
view_width_ = new_view_width;
view_height_ = new_view_height;
should_update_metrics = true;
}
break;
}
case fuchsia::ui::gfx::Event::Tag::kViewConnected:
......@@ -372,6 +289,26 @@ void PlatformView::OnScenicEvent(
}
}
}
if (should_update_metrics) {
SetViewportMetrics({
view_pixel_ratio_, // device_pixel_ratio
view_width_ * view_pixel_ratio_, // physical_width
view_height_ * view_pixel_ratio_, // physical_height
0.0f, // physical_padding_top
0.0f, // physical_padding_right
0.0f, // physical_padding_bottom
0.0f, // physical_padding_left
0.0f, // physical_view_inset_top
0.0f, // physical_view_inset_right
0.0f, // physical_view_inset_bottom
0.0f, // physical_view_inset_left
0.0f, // p_physical_system_gesture_inset_top
0.0f, // p_physical_system_gesture_inset_right
0.0f, // p_physical_system_gesture_inset_bottom
0.0f, // p_physical_system_gesture_inset_left
});
}
}
void PlatformView::OnChildViewConnected(scenic::ResourceId view_holder_id) {
......@@ -451,8 +388,9 @@ bool PlatformView::OnHandlePointerEvent(
pointer_data.change = GetChangeFromPointerEventPhase(pointer.phase);
pointer_data.kind = GetKindFromPointerType(pointer.type);
pointer_data.device = pointer.pointer_id;
pointer_data.physical_x = pointer.x * metrics_.scale;
pointer_data.physical_y = pointer.y * metrics_.scale;
// Pointer events are in logical pixels, so scale to physical.
pointer_data.physical_x = pointer.x * view_pixel_ratio_;
pointer_data.physical_y = pointer.y * view_pixel_ratio_;
// Buttons are single bit values starting with kMousePrimaryButton = 1.
pointer_data.buttons = static_cast<uint64_t>(pointer.buttons);
......
......@@ -5,7 +5,6 @@
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_PLATFORM_VIEW_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_PLATFORM_VIEW_H_
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/fit/function.h>
......@@ -14,7 +13,6 @@
#include <set>
#include "flutter/fml/macros.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/fuchsia/flutter/accessibility_bridge.h"
#include "flutter_runner_product_configuration.h"
......@@ -24,9 +22,6 @@
namespace flutter_runner {
using OnMetricsUpdate = fit::function<void(const fuchsia::ui::gfx::Metrics&)>;
using OnSizeChangeHint =
fit::function<void(float width_change_factor, float height_change_factor)>;
using OnEnableWireframe = fit::function<void(bool)>;
using OnCreateView = fit::function<void(int64_t, bool, bool)>;
using OnDestroyView = fit::function<void(int64_t)>;
......@@ -53,25 +48,15 @@ class PlatformView final : public flutter::PlatformView,
fidl::InterfaceRequest<fuchsia::ui::scenic::SessionListener>
session_listener_request,
fit::closure on_session_listener_error_callback,
OnMetricsUpdate session_metrics_did_change_callback,
OnSizeChangeHint session_size_change_hint_callback,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnDestroyView on_destroy_view_callback,
OnGetViewEmbedder on_get_view_embedder_callback,
zx_handle_t vsync_event_handle,
FlutterRunnerProductConfiguration product_config);
PlatformView(flutter::PlatformView::Delegate& delegate,
std::string debug_label,
flutter::TaskRunners task_runners,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider>
parent_environment_service_provider,
zx_handle_t vsync_event_handle);
~PlatformView();
void UpdateViewportMetrics(const fuchsia::ui::gfx::Metrics& metrics);
// |flutter::PlatformView|
// |flutter_runner::AccessibilityBridge::Delegate|
void SetSemanticsEnabled(bool enabled) override;
......@@ -92,8 +77,6 @@ class PlatformView final : public flutter::PlatformView,
fidl::Binding<fuchsia::ui::scenic::SessionListener> session_listener_binding_;
fit::closure session_listener_error_callback_;
OnMetricsUpdate metrics_changed_callback_;
OnSizeChangeHint size_change_hint_callback_;
OnEnableWireframe wireframe_enabled_callback_;
OnCreateView on_create_view_callback_;
OnDestroyView on_destroy_view_callback_;
......@@ -105,8 +88,7 @@ class PlatformView final : public flutter::PlatformView,
fuchsia::ui::input::ImeServicePtr text_sync_service_;
fuchsia::sys::ServiceProviderPtr parent_environment_service_provider_;
flutter::LogicalMetrics metrics_;
fuchsia::ui::gfx::Metrics scenic_metrics_;
// last_text_state_ is the last state of the text input as reported by the IME
// or initialized by Flutter. We set it to null if Flutter doesn't want any
// input, since then there is no text input state at all.
......@@ -124,16 +106,14 @@ class PlatformView final : public flutter::PlatformView,
std::set<std::string /* channel */> unregistered_channels_;
zx_handle_t vsync_event_handle_ = 0;
float view_width_ = 0.0f; // Width in logical pixels.
float view_height_ = 0.0f; // Height in logical pixels.
float view_pixel_ratio_ = 0.0f; // Logical / physical pixel ratio.
FlutterRunnerProductConfiguration product_config_;
void RegisterPlatformMessageHandlers();
void FlushViewportMetrics();
// Called when the view's properties have changed.
void OnPropertiesChanged(
const fuchsia::ui::gfx::ViewProperties& view_properties);
// |fuchsia::ui::input::InputMethodEditorClient|
void DidUpdateState(
fuchsia::ui::input::TextInputState state,
......
......@@ -4,7 +4,7 @@
#include "flutter/shell/platform/fuchsia/flutter/platform_view.h"
#include <gtest/gtest.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/default.h>
......@@ -15,11 +15,11 @@
#include <memory>
#include <vector>
#include "flutter/flow/scene_update_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/lib/ui/window/window.h"
#include "fuchsia/ui/views/cpp/fidl.h"
#include "gtest/gtest.h"
#include "task_runner_adapter.h"
namespace flutter_runner_test::flutter_runner_a11y_test {
......@@ -41,6 +41,33 @@ class PlatformViewTests : public testing::Test {
FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewTests);
};
class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
public:
MockExternalViewEmbedder() = default;
~MockExternalViewEmbedder() override = default;
SkCanvas* GetRootCanvas() override { return nullptr; }
std::vector<SkCanvas*> GetCurrentCanvases() override {
return std::vector<SkCanvas*>();
}
void CancelFrame() override {}
void BeginFrame(
SkISize frame_size,
GrDirectContext* context,
double device_pixel_ratio,
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {}
void SubmitFrame(GrDirectContext* context,
std::unique_ptr<flutter::SurfaceFrame> frame) override {
return;
}
void PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<flutter::EmbeddedViewParams> params) override {}
SkCanvas* CompositeEmbeddedView(int view_id) override { return nullptr; }
};
class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
public:
// |flutter::PlatformView::Delegate|
......@@ -99,30 +126,6 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
int32_t semantics_features_ = 0;
};
class MockSurfaceProducer
: public flutter::SceneUpdateContext::SurfaceProducer {
public:
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
ProduceSurface(const SkISize& size,
const flutter::LayerRasterCacheKey& layer_key,
std::unique_ptr<scenic::EntityNode> entity_node) override {
return nullptr;
}
bool HasRetainedNode(const flutter::LayerRasterCacheKey& key) const override {
return false;
}
scenic::EntityNode* GetRetainedNode(
const flutter::LayerRasterCacheKey& key) override {
return nullptr;
}
void SubmitSurface(
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
surface) override {}
};
TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
......@@ -147,8 +150,6 @@ TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // on_session_listener_error_callback
nullptr, // session_metrics_did_change_callback
nullptr, // session_size_change_hint_callback
nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
......@@ -203,8 +204,6 @@ TEST_F(PlatformViewTests, EnableWireframeTest) {
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // on_session_listener_error_callback
nullptr, // session_metrics_did_change_callback
nullptr, // session_size_change_hint_callback
EnableWireframeCallback, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
......@@ -270,8 +269,6 @@ TEST_F(PlatformViewTests, CreateViewTest) {
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // on_session_listener_error_callback
nullptr, // session_metrics_did_change_callback
nullptr, // session_size_change_hint_callback
nullptr, // on_enable_wireframe_callback,
CreateViewCallback, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
......@@ -339,8 +336,6 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // on_session_listener_error_callback
nullptr, // session_metrics_did_change_callback
nullptr, // session_size_change_hint_callback
nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
DestroyViewCallback, // on_destroy_view_callback,
......@@ -395,11 +390,8 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) {
);
// Test get view embedder callback function.
MockSurfaceProducer surfaceProducer;
flutter::SceneUpdateContext scene_update_context(nullptr, &surfaceProducer);
flutter::ExternalViewEmbedder* view_embedder =
reinterpret_cast<flutter::ExternalViewEmbedder*>(&scene_update_context);
auto GetViewEmbedderCallback = [view_embedder]() { return view_embedder; };
MockExternalViewEmbedder view_embedder;
auto GetViewEmbedderCallback = [&view_embedder]() { return &view_embedder; };
auto platform_view = flutter_runner::PlatformView(
delegate, // delegate
......@@ -410,8 +402,6 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) {
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // on_session_listener_error_callback
nullptr, // session_metrics_did_change_callback
nullptr, // session_size_change_hint_callback
nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
......@@ -426,7 +416,7 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) {
RunLoopUntilIdle();
EXPECT_EQ(view_embedder, delegate.get_view_embedder());
EXPECT_EQ(&view_embedder, delegate.get_view_embedder());
}
} // namespace flutter_runner_test::flutter_runner_a11y_test
......@@ -5,8 +5,8 @@
#include "session_connection.h"
#include "flutter/fml/make_copyable.h"
#include "lib/fidl/cpp/optional.h"
#include "lib/ui/scenic/cpp/commands.h"
#include "flutter/fml/trace_event.h"
#include "vsync_recorder.h"
#include "vsync_waiter.h"
......@@ -14,23 +14,11 @@ namespace flutter_runner {
SessionConnection::SessionConnection(
std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
fidl::InterfaceHandle<fuchsia::ui::scenic::Session> session,
fml::closure session_error_callback,
on_frame_presented_event on_frame_presented_callback,
zx_handle_t vsync_event_handle)
: debug_label_(std::move(debug_label)),
session_wrapper_(session.Bind(), nullptr),
root_view_(&session_wrapper_,
std::move(view_token),
std::move(view_ref_pair.control_ref),
std::move(view_ref_pair.view_ref),
debug_label),
root_node_(&session_wrapper_),
surface_producer_(
std::make_unique<VulkanSurfaceProducer>(&session_wrapper_)),
scene_update_context_(&session_wrapper_, surface_producer_.get()),
: session_wrapper_(session.Bind(), nullptr),
on_frame_presented_callback_(std::move(on_frame_presented_callback)),
vsync_event_handle_(vsync_event_handle) {
session_wrapper_.set_error_handler(
......@@ -63,11 +51,7 @@ SessionConnection::SessionConnection(
} // callback
);
session_wrapper_.SetDebugName(debug_label_);
root_view_.AddChild(root_node_);
root_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask |
fuchsia::ui::gfx::kSizeChangeHintEventMask);
session_wrapper_.SetDebugName(debug_label);
// Get information to finish initialization and only then allow Present()s.
session_wrapper_.RequestPresentationTimes(
......@@ -91,8 +75,7 @@ SessionConnection::SessionConnection(
SessionConnection::~SessionConnection() = default;
void SessionConnection::Present(
flutter::CompositorContext::ScopedFrame* frame) {
void SessionConnection::Present() {
TRACE_EVENT0("gfx", "SessionConnection::Present");
TRACE_FLOW_BEGIN("gfx", "SessionConnection::PresentSession",
......@@ -114,21 +97,6 @@ void SessionConnection::Present(
present_session_pending_ = true;
ToggleSignal(vsync_event_handle_, false);
}
if (frame) {
// Execute paint tasks and signal fences.
auto surfaces_to_submit = scene_update_context_.ExecutePaintTasks(*frame);
// Tell the surface producer that a present has occurred so it can perform
// book-keeping on buffer caches.
surface_producer_->OnSurfacesPresented(std::move(surfaces_to_submit));
}
}
void SessionConnection::OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor) {
surface_producer_->OnSessionSizeChangeHint(width_change_factor,
height_change_factor);
}
fml::TimePoint SessionConnection::CalculateNextLatchPoint(
......@@ -160,17 +128,6 @@ fml::TimePoint SessionConnection::CalculateNextLatchPoint(
return minimum_latch_point_to_target;
}
void SessionConnection::set_enable_wireframe(bool enable) {
session_wrapper_.Enqueue(
scenic::NewSetEnableDebugViewBoundsCmd(root_view_.id(), enable));
}
void SessionConnection::EnqueueClearOps() {
// 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_wrapper_.Enqueue(scenic::NewDetachChildrenCmd(root_node_.id()));
}
void SessionConnection::PresentSession() {
TRACE_EVENT0("gfx", "SessionConnection::PresentSession");
......@@ -232,10 +189,6 @@ void SessionConnection::PresentSession() {
VsyncRecorder::GetInstance().UpdateNextPresentationInfo(
std::move(info));
});
// Prepare for the next frame. These ops won't be processed till the next
// present.
EnqueueClearOps();
}
void SessionConnection::ToggleSignal(zx_handle_t handle, bool set) {
......
......@@ -5,22 +5,14 @@
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_SESSION_CONNECTION_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_SESSION_CONNECTION_H_
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/scenic/scheduling/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fidl/cpp/interface_handle.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/fit/function.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/session.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/trace_event.h"
#include "vulkan_surface_producer.h"
namespace flutter_runner {
......@@ -29,11 +21,9 @@ using on_frame_presented_event =
// The component residing on the raster thread that is responsible for
// maintaining the Scenic session connection and presenting node updates.
class SessionConnection final {
class SessionConnection final : public flutter::SessionWrapper {
public:
SessionConnection(std::string debug_label,
fuchsia::ui::views::ViewToken view_token,
scenic::ViewRefPair view_ref_pair,
fidl::InterfaceHandle<fuchsia::ui::scenic::Session> session,
fml::closure session_error_callback,
on_frame_presented_event on_frame_presented_callback,
......@@ -41,36 +31,8 @@ class SessionConnection final {
~SessionConnection();
bool has_metrics() const { return scene_update_context_.has_metrics(); }
const fuchsia::ui::gfx::MetricsPtr& metrics() const {
return scene_update_context_.metrics();
}
void set_metrics(const fuchsia::ui::gfx::Metrics& metrics) {
fuchsia::ui::gfx::Metrics metrics_copy;
metrics.Clone(&metrics_copy);
scene_update_context_.set_metrics(
fidl::MakeOptional(std::move(metrics_copy)));
}
void set_enable_wireframe(bool enable);
flutter::SceneUpdateContext& scene_update_context() {
return scene_update_context_;
}
scenic::ContainerNode& root_node() { return root_node_; }
scenic::View* root_view() { return &root_view_; }
void Present(flutter::CompositorContext::ScopedFrame* frame);
void OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor);
VulkanSurfaceProducer* vulkan_surface_producer() {
return surface_producer_.get();
}
scenic::Session* get() override { return &session_wrapper_; }
void Present() override;
static fml::TimePoint CalculateNextLatchPoint(
fml::TimePoint present_requested_time,
......@@ -82,14 +44,8 @@ class SessionConnection final {
future_presentation_infos);
private:
const std::string debug_label_;
scenic::Session session_wrapper_;
scenic::View root_view_;
scenic::EntityNode root_node_;
std::unique_ptr<VulkanSurfaceProducer> surface_producer_;
flutter::SceneUpdateContext scene_update_context_;
on_frame_presented_event on_frame_presented_callback_;
zx_handle_t vsync_event_handle_;
......@@ -122,8 +78,6 @@ class SessionConnection final {
bool present_session_pending_ = false;
void EnqueueClearOps();
void PresentSession();
static void ToggleSignal(zx_handle_t handle, bool raise);
......
......@@ -2,18 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gtest/gtest.h"
#include <fuchsia/scenic/scheduling/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/async-loop/default.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include "flutter/shell/platform/fuchsia/flutter/logging.h"
#include "flutter/shell/platform/fuchsia/flutter/runner.h"
#include "flutter/shell/platform/fuchsia/flutter/session_connection.h"
#include "gtest/gtest.h"
using namespace flutter_runner;
......@@ -30,12 +28,8 @@ class SessionConnectionTest : public ::testing::Test {
loop_.StartThread("SessionConnectionTestThread", &fidl_thread_));
auto session_listener_request = session_listener_.NewRequest();
auto [view_token, view_holder_token] = scenic::ViewTokenPair::New();
view_token_ = std::move(view_token);
scenic_->CreateSession(session_.NewRequest(), session_listener_.Bind());
presenter_->PresentOrReplaceView(std::move(view_holder_token), nullptr);
FML_CHECK(zx::event::create(0, &vsync_event_) == ZX_OK);
// Ensure Scenic has had time to wake up before the test logic begins.
......@@ -60,7 +54,6 @@ class SessionConnectionTest : public ::testing::Test {
fidl::InterfaceHandle<fuchsia::ui::scenic::Session> session_;
fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> session_listener_;
fuchsia::ui::views::ViewToken view_token_;
zx::event vsync_event_;
thrd_t fidl_thread_;
};
......@@ -76,12 +69,11 @@ TEST_F(SessionConnectionTest, SimplePresentTest) {
};
flutter_runner::SessionConnection session_connection(
"debug label", std::move(view_token_), scenic::ViewRefPair::New(),
std::move(session_), on_session_error_callback,
"debug label", std::move(session_), on_session_error_callback,
on_frame_presented_callback, vsync_event_.get());
for (int i = 0; i < 200; ++i) {
session_connection.Present(nullptr);
session_connection.Present();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
......@@ -99,12 +91,11 @@ TEST_F(SessionConnectionTest, BatchedPresentTest) {
};
flutter_runner::SessionConnection session_connection(
"debug label", std::move(view_token_), scenic::ViewRefPair::New(),
std::move(session_), on_session_error_callback,
"debug label", std::move(session_), on_session_error_callback,
on_frame_presented_callback, vsync_event_.get());
for (int i = 0; i < 200; ++i) {
session_connection.Present(nullptr);
session_connection.Present();
if (i % 10 == 9) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
......
......@@ -5,6 +5,7 @@
#pragma once
#include <lib/async/cpp/wait.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/zx/event.h>
#include <lib/zx/vmo.h>
......@@ -12,17 +13,46 @@
#include <memory>
#include "flutter/flow/raster_cache_key.h"
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h"
#include "flutter/vulkan/vulkan_command_buffer.h"
#include "flutter/vulkan/vulkan_handle.h"
#include "flutter/vulkan/vulkan_proc_table.h"
#include "flutter/vulkan/vulkan_provider.h"
#include "lib/ui/scenic/cpp/resources.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace flutter_runner {
class SurfaceProducerSurface {
public:
virtual ~SurfaceProducerSurface() = default;
virtual size_t AdvanceAndGetAge() = 0;
virtual bool FlushSessionAcquireAndReleaseEvents() = 0;
virtual bool IsValid() const = 0;
virtual SkISize GetSize() const = 0;
virtual void SignalWritesFinished(
const std::function<void(void)>& on_writes_committed) = 0;
virtual scenic::Image* GetImage() = 0;
virtual sk_sp<SkSurface> GetSkiaSurface() const = 0;
};
class SurfaceProducer {
public:
virtual ~SurfaceProducer() = default;
virtual std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
const SkISize& size) = 0;
virtual void SubmitSurface(
std::unique_ptr<SurfaceProducerSurface> surface) = 0;
};
// A |VkImage| and its relevant metadata.
struct VulkanImage {
VulkanImage() = default;
......@@ -44,8 +74,7 @@ bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider,
const SkISize& size,
VulkanImage* out_vulkan_image);
class VulkanSurface final
: public flutter::SceneUpdateContext::SurfaceProducerSurface {
class VulkanSurface final : public SurfaceProducerSurface {
public:
VulkanSurface(vulkan::VulkanProvider& vulkan_provider,
sk_sp<GrDirectContext> context,
......@@ -54,16 +83,16 @@ class VulkanSurface final
~VulkanSurface() override;
// |flutter::SceneUpdateContext::SurfaceProducerSurface|
// |SurfaceProducerSurface|
size_t AdvanceAndGetAge() override;
// |flutter::SceneUpdateContext::SurfaceProducerSurface|
// |SurfaceProducerSurface|
bool FlushSessionAcquireAndReleaseEvents() override;
// |flutter::SceneUpdateContext::SurfaceProducerSurface|
// |SurfaceProducerSurface|
bool IsValid() const override;
// |flutter::SceneUpdateContext::SurfaceProducerSurface|
// |SurfaceProducerSurface|
SkISize GetSize() const override;
// Note: It is safe for the caller to collect the surface in the
......@@ -71,10 +100,10 @@ class VulkanSurface final
void SignalWritesFinished(
const std::function<void(void)>& on_writes_committed) override;
// |flutter::SceneUpdateContext::SurfaceProducerSurface|
// |SurfaceProducerSurface|
scenic::Image* GetImage() override;
// |flutter::SceneUpdateContext::SurfaceProducerSurface|
// |SurfaceProducerSurface|
sk_sp<SkSurface> GetSkiaSurface() const override;
const vulkan::VulkanHandle<VkImage>& GetVkImage() {
......@@ -119,41 +148,6 @@ class VulkanSurface final
// if the swap was not successful.
bool BindToImage(sk_sp<GrDirectContext> context, VulkanImage vulkan_image);
// Flutter may retain a |VulkanSurface| for a |flutter::Layer| subtree to
// improve the performance. The |retained_key_| identifies which layer subtree
// this |VulkanSurface| is retained for. The key has two parts. One is the
// pointer to the root of that layer subtree: |retained_key_.id()|. Another is
// the transformation matrix: |retained_key_.matrix()|. We need the matrix
// part because a different matrix would invalidate the pixels (raster cache)
// in this |VulkanSurface|.
const flutter::LayerRasterCacheKey& GetRetainedKey() const {
return retained_key_;
}
// For better safety in retained rendering, Flutter uses a retained
// |EntityNode| associated with the retained surface instead of using the
// retained surface directly. Hence Flutter can't modify the surface during
// retained rendering. However, the node itself is modifiable to be able
// to adjust its position.
scenic::EntityNode* GetRetainedNode() {
used_in_retained_rendering_ = true;
return retained_node_.get();
}
// Check whether the retained surface (and its associated |EntityNode|) is
// used in the current frame or not. If unused, the |VulkanSurfacePool| will
// try to recycle the surface. This flag is reset after each frame.
bool IsUsedInRetainedRendering() const { return used_in_retained_rendering_; }
void ResetIsUsedInRetainedRendering() { used_in_retained_rendering_ = false; }
// Let this surface own the retained EntityNode associated with it (see
// |GetRetainedNode|), and set the retained key (see |GetRetainedKey|).
void SetRetainedInfo(const flutter::LayerRasterCacheKey& key,
std::unique_ptr<scenic::EntityNode> node) {
retained_key_ = key;
retained_node_ = std::move(node);
}
private:
static constexpr int kSizeHistorySize = 4;
......@@ -202,11 +196,6 @@ class VulkanSurface final
size_t age_ = 0;
bool valid_ = false;
flutter::LayerRasterCacheKey retained_key_ = {0, SkMatrix::Scale(1, 1)};
std::unique_ptr<scenic::EntityNode> retained_node_ = nullptr;
std::atomic<bool> used_in_retained_rendering_ = {false};
FML_DISALLOW_COPY_AND_ASSIGN(VulkanSurface);
};
......
......@@ -112,8 +112,7 @@ std::unique_ptr<VulkanSurface> VulkanSurfacePool::GetCachedOrCreateSurface(
}
void VulkanSurfacePool::SubmitSurface(
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
p_surface) {
std::unique_ptr<SurfaceProducerSurface> p_surface) {
TRACE_EVENT0("flutter", "VulkanSurfacePool::SubmitSurface");
// This cast is safe because |VulkanSurface| is the only implementation of
......@@ -126,43 +125,14 @@ void VulkanSurfacePool::SubmitSurface(
return;
}
const flutter::LayerRasterCacheKey& retained_key =
vulkan_surface->GetRetainedKey();
// TODO(https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=44141): Re-enable
// retained surfaces after we find out why textures are being prematurely
// recycled.
const bool kUseRetainedSurfaces = false;
if (kUseRetainedSurfaces && retained_key.id() != 0) {
// Add the surface to |retained_surfaces_| if its retained key has a valid
// layer id (|retained_key.id()|).
//
// We have to add the entry to |retained_surfaces_| map early when it's
// still pending (|is_pending| = true). Otherwise (if we add the surface
// later when |SignalRetainedReady| is called), Flutter would fail to find
// the retained node before the painting is done (which could take multiple
// frames). Flutter would then create a new |VulkanSurface| for the layer
// upon the failed lookup. The new |VulkanSurface| would invalidate this
// surface, and before the new |VulkanSurface| is done painting, another
// newer |VulkanSurface| is likely to be created to replace the new
// |VulkanSurface|. That would make the retained rendering much less useful
// in improving the performance.
auto insert_iterator = retained_surfaces_.insert(std::make_pair(
retained_key, RetainedSurface({true, std::move(vulkan_surface)})));
if (insert_iterator.second) {
insert_iterator.first->second.vk_surface->SignalWritesFinished(std::bind(
&VulkanSurfacePool::SignalRetainedReady, this, retained_key));
}
} else {
uintptr_t surface_key = reinterpret_cast<uintptr_t>(vulkan_surface.get());
auto insert_iterator = pending_surfaces_.insert(std::make_pair(
surface_key, // key
std::move(vulkan_surface) // value
));
if (insert_iterator.second) {
insert_iterator.first->second->SignalWritesFinished(std::bind(
&VulkanSurfacePool::RecyclePendingSurface, this, surface_key));
}
uintptr_t surface_key = reinterpret_cast<uintptr_t>(vulkan_surface.get());
auto insert_iterator = pending_surfaces_.insert(std::make_pair(
surface_key, // key
std::move(vulkan_surface) // value
));
if (insert_iterator.second) {
insert_iterator.first->second->SignalWritesFinished(std::bind(
&VulkanSurfacePool::RecyclePendingSurface, this, surface_key));
}
}
......@@ -213,25 +183,6 @@ void VulkanSurfacePool::RecycleSurface(std::unique_ptr<VulkanSurface> surface) {
TraceStats();
}
void VulkanSurfacePool::RecycleRetainedSurface(
const flutter::LayerRasterCacheKey& key) {
auto it = retained_surfaces_.find(key);
if (it == retained_surfaces_.end()) {
return;
}
// The surface should not be pending.
FML_DCHECK(!it->second.is_pending);
auto surface_to_recycle = std::move(it->second.vk_surface);
retained_surfaces_.erase(it);
RecycleSurface(std::move(surface_to_recycle));
}
void VulkanSurfacePool::SignalRetainedReady(flutter::LayerRasterCacheKey key) {
retained_surfaces_[key].is_pending = false;
}
void VulkanSurfacePool::AgeAndCollectOldBuffers() {
TRACE_EVENT0("flutter", "VulkanSurfacePool::AgeAndCollectOldBuffers");
......@@ -268,25 +219,6 @@ void VulkanSurfacePool::AgeAndCollectOldBuffers() {
}
}
// Recycle retained surfaces that are not used and not pending in this frame.
//
// It's safe to recycle any retained surfaces that are not pending no matter
// whether they're used or not. Hence if there's memory pressure, feel free to
// recycle all retained surfaces that are not pending.
std::vector<flutter::LayerRasterCacheKey> recycle_keys;
for (auto& [key, retained_surface] : retained_surfaces_) {
if (retained_surface.is_pending ||
retained_surface.vk_surface->IsUsedInRetainedRendering()) {
// Reset the flag for the next frame
retained_surface.vk_surface->ResetIsUsedInRetainedRendering();
} else {
recycle_keys.push_back(key);
}
}
for (auto& key : recycle_keys) {
RecycleRetainedSurface(key);
}
TraceStats();
}
......@@ -320,15 +252,9 @@ void VulkanSurfacePool::ShrinkToFit() {
void VulkanSurfacePool::TraceStats() {
// Resources held in cached buffers.
size_t cached_surfaces_bytes = 0;
size_t retained_surfaces_bytes = 0;
for (const auto& surface : available_surfaces_) {
cached_surfaces_bytes += surface->GetAllocationSize();
}
for (const auto& retained_entry : retained_surfaces_) {
retained_surfaces_bytes +=
retained_entry.second.vk_surface->GetAllocationSize();
}
// Resources held by Skia.
int skia_resources = 0;
......@@ -342,13 +268,13 @@ void VulkanSurfacePool::TraceStats() {
"Created", trace_surfaces_created_, //
"Reused", trace_surfaces_reused_, //
"PendingInCompositor", pending_surfaces_.size(), //
"Retained", retained_surfaces_.size(), //
"Retained", 0, //
"SkiaCacheResources", skia_resources //
);
TRACE_COUNTER("flutter", "SurfacePoolBytes", 0u, //
"CachedBytes", cached_surfaces_bytes, //
"RetainedBytes", retained_surfaces_bytes, //
"RetainedBytes", 0, //
"SkiaCacheBytes", skia_bytes, //
"SkiaCachePurgeable", skia_cache_purgeable //
);
......
......@@ -28,9 +28,7 @@ class VulkanSurfacePool final {
std::unique_ptr<VulkanSurface> AcquireSurface(const SkISize& size);
void SubmitSurface(
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
surface);
void SubmitSurface(std::unique_ptr<SurfaceProducerSurface> surface);
void AgeAndCollectOldBuffers();
......@@ -38,26 +36,7 @@ class VulkanSurfacePool final {
// small as they can be.
void ShrinkToFit();
// For |VulkanSurfaceProducer::HasRetainedNode|.
bool HasRetainedNode(const flutter::LayerRasterCacheKey& key) const {
return retained_surfaces_.find(key) != retained_surfaces_.end();
}
// For |VulkanSurfaceProducer::GetRetainedNode|.
scenic::EntityNode* GetRetainedNode(const flutter::LayerRasterCacheKey& key) {
FML_DCHECK(HasRetainedNode(key));
return retained_surfaces_[key].vk_surface->GetRetainedNode();
}
private:
// Struct for retained_surfaces_ map.
struct RetainedSurface {
// If |is_pending| is true, the |vk_surface| is still under painting
// (similar to those in |pending_surfaces_|) so we can't recycle the
// |vk_surface| yet.
bool is_pending;
std::unique_ptr<VulkanSurface> vk_surface;
};
vulkan::VulkanProvider& vulkan_provider_;
sk_sp<GrDirectContext> context_;
scenic::Session* scenic_session_;
......@@ -65,9 +44,6 @@ class VulkanSurfacePool final {
std::unordered_map<uintptr_t, std::unique_ptr<VulkanSurface>>
pending_surfaces_;
// Retained surfaces keyed by the layer that created and used the surface.
flutter::LayerRasterCacheKey::Map<RetainedSurface> retained_surfaces_;
size_t trace_surfaces_created_ = 0;
size_t trace_surfaces_reused_ = 0;
......@@ -79,13 +55,6 @@ class VulkanSurfacePool final {
void RecyclePendingSurface(uintptr_t surface_key);
// Clear the |is_pending| flag of the retained surface.
void SignalRetainedReady(flutter::LayerRasterCacheKey key);
// Remove the corresponding surface from |retained_surfaces| and recycle it.
// The surface must not be pending.
void RecycleRetainedSurface(const flutter::LayerRasterCacheKey& key);
void TraceStats();
FML_DISALLOW_COPY_AND_ASSIGN(VulkanSurfacePool);
......
......@@ -155,9 +155,7 @@ bool VulkanSurfaceProducer::Initialize(scenic::Session* scenic_session) {
}
void VulkanSurfaceProducer::OnSurfacesPresented(
std::vector<
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>>
surfaces) {
std::vector<std::unique_ptr<SurfaceProducerSurface>> surfaces) {
TRACE_EVENT0("flutter", "VulkanSurfaceProducer::OnSurfacesPresented");
// Do a single flush for all canvases derived from the context.
......@@ -197,11 +195,12 @@ void VulkanSurfaceProducer::OnSurfacesPresented(
}
bool VulkanSurfaceProducer::TransitionSurfacesToExternal(
const std::vector<
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>>&
surfaces) {
const std::vector<std::unique_ptr<SurfaceProducerSurface>>& surfaces) {
for (auto& surface : surfaces) {
auto vk_surface = static_cast<VulkanSurface*>(surface.get());
if (!vk_surface) {
continue;
}
vulkan::VulkanCommandBuffer* command_buffer =
vk_surface->GetCommandBuffer(logical_device_->GetCommandPool());
......@@ -259,21 +258,15 @@ bool VulkanSurfaceProducer::TransitionSurfacesToExternal(
return true;
}
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
VulkanSurfaceProducer::ProduceSurface(
const SkISize& size,
const flutter::LayerRasterCacheKey& layer_key,
std::unique_ptr<scenic::EntityNode> entity_node) {
std::unique_ptr<SurfaceProducerSurface> VulkanSurfaceProducer::ProduceSurface(
const SkISize& size) {
FML_DCHECK(valid_);
last_produce_time_ = async::Now(async_get_default_dispatcher());
auto surface = surface_pool_->AcquireSurface(size);
surface->SetRetainedInfo(layer_key, std::move(entity_node));
return surface;
return surface_pool_->AcquireSurface(size);
}
void VulkanSurfaceProducer::SubmitSurface(
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
surface) {
std::unique_ptr<SurfaceProducerSurface> surface) {
FML_DCHECK(valid_ && surface != nullptr);
surface_pool_->SubmitSurface(std::move(surface));
}
......
......@@ -8,8 +8,8 @@
#include <lib/async/default.h>
#include <lib/syslog/global.h>
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/vulkan/vulkan_application.h"
#include "flutter/vulkan/vulkan_device.h"
#include "flutter/vulkan/vulkan_proc_table.h"
......@@ -22,9 +22,8 @@
namespace flutter_runner {
class VulkanSurfaceProducer final
: public flutter::SceneUpdateContext::SurfaceProducer,
public vulkan::VulkanProvider {
class VulkanSurfaceProducer final : public SurfaceProducer,
public vulkan::VulkanProvider {
public:
VulkanSurfaceProducer(scenic::Session* scenic_session);
......@@ -32,39 +31,15 @@ class VulkanSurfaceProducer final
bool IsValid() const { return valid_; }
// |flutter::SceneUpdateContext::SurfaceProducer|
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
ProduceSurface(const SkISize& size,
const flutter::LayerRasterCacheKey& layer_key,
std::unique_ptr<scenic::EntityNode> entity_node) override;
// |SurfaceProducer|
std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
const SkISize& size) override;
// |flutter::SceneUpdateContext::SurfaceProducer|
void SubmitSurface(
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
surface) override;
// |flutter::SceneUpdateContext::HasRetainedNode|
bool HasRetainedNode(const flutter::LayerRasterCacheKey& key) const override {
return surface_pool_->HasRetainedNode(key);
}
// |flutter::SceneUpdateContext::GetRetainedNode|
scenic::EntityNode* GetRetainedNode(
const flutter::LayerRasterCacheKey& key) override {
return surface_pool_->GetRetainedNode(key);
}
// |SurfaceProducer|
void SubmitSurface(std::unique_ptr<SurfaceProducerSurface> surface) override;
void OnSurfacesPresented(
std::vector<
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>>
surfaces);
void OnSessionSizeChangeHint(float width_change_factor,
float height_change_factor) {
FX_LOGF(INFO, LOG_TAG,
"VulkanSurfaceProducer:OnSessionSizeChangeHint %f, %f",
width_change_factor, height_change_factor);
}
std::vector<std::unique_ptr<SurfaceProducerSurface>> surfaces);
GrDirectContext* gr_context() { return context_.get(); }
......@@ -76,9 +51,7 @@ class VulkanSurfaceProducer final
}
bool TransitionSurfacesToExternal(
const std::vector<
std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>>&
surfaces);
const std::vector<std::unique_ptr<SurfaceProducerSurface>>& surfaces);
// Note: the order here is very important. The proctable must be destroyed
// last because it contains the function pointers for VkDestroyDevice and
......
......@@ -46,7 +46,6 @@ void main() {
double? oldDPR;
Size? oldSize;
double? oldDepth;
WindowPadding? oldPadding;
WindowPadding? oldInsets;
WindowPadding? oldSystemGestureInsets;
......@@ -54,7 +53,6 @@ void main() {
void setUp() {
oldDPR = window.devicePixelRatio;
oldSize = window.physicalSize;
oldDepth = window.physicalDepth;
oldPadding = window.viewPadding;
oldInsets = window.viewInsets;
oldSystemGestureInsets = window.systemGestureInsets;
......@@ -76,7 +74,6 @@ void main() {
oldDPR!, // DPR
oldSize!.width, // width
oldSize!.height, // height
oldDepth!, // depth
oldPadding!.top, // padding top
oldPadding!.right, // padding right
oldPadding!.bottom, // padding bottom
......@@ -161,7 +158,6 @@ void main() {
0.1234, // DPR
0.0, // width
0.0, // height
0.0, // depth
0.0, // padding top
0.0, // padding right
0.0, // padding bottom
......@@ -378,7 +374,6 @@ void main() {
1.0, // DPR
800.0, // width
600.0, // height
100.0, // depth
50.0, // padding top
0.0, // padding right
40.0, // padding bottom
......@@ -396,14 +391,12 @@ void main() {
expectEquals(window.viewInsets.bottom, 0.0);
expectEquals(window.viewPadding.bottom, 40.0);
expectEquals(window.padding.bottom, 40.0);
expectEquals(window.physicalDepth, 100.0);
expectEquals(window.systemGestureInsets.bottom, 0.0);
_updateWindowMetrics(
1.0, // DPR
800.0, // width
600.0, // height
100.0, // depth
50.0, // padding top
0.0, // padding right
40.0, // padding bottom
......@@ -421,7 +414,6 @@ void main() {
expectEquals(window.viewInsets.bottom, 400.0);
expectEquals(window.viewPadding.bottom, 40.0);
expectEquals(window.padding.bottom, 0.0);
expectEquals(window.physicalDepth, 100.0);
expectEquals(window.systemGestureInsets.bottom, 44.0);
});
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册