mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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
This commit is contained in:
parent
033dd45607
commit
12a37478de
@ -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);
|
||||
SkScalarRoundToInt(context.alphaf() * 255), "flutter::ContainerLayer");
|
||||
frame->AddPaintLayer(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();
|
||||
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;
|
||||
FML_DCHECK(needs_system_composite());
|
||||
FML_DCHECK(child_layer_exists_below_);
|
||||
|
||||
// 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());
|
||||
SceneUpdateContext::Frame frame(
|
||||
context, SkRRect::MakeRect(paint_bounds()), SK_ColorTRANSPARENT,
|
||||
SkScalarRoundToInt(context.alphaf() * 255), "flutter::Layer");
|
||||
|
||||
// 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);
|
||||
}
|
||||
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_);
|
||||
// Reset for a new Scene.
|
||||
context.Reset();
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
|
||||
} // 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::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);
|
||||
|
||||
// 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)});
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 SessionWrapper {
|
||||
public:
|
||||
virtual ~SessionWrapper() {}
|
||||
|
||||
virtual scenic::Session* get() = 0;
|
||||
virtual void Present() = 0;
|
||||
};
|
||||
|
||||
class SceneUpdateContext : public flutter::ExternalViewEmbedder {
|
||||
public:
|
||||
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;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
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);
|
||||
struct PaintTask {
|
||||
SkRect paint_bounds;
|
||||
SkScalar scale_x;
|
||||
SkScalar scale_y;
|
||||
SkColor background_color;
|
||||
scenic::Material material;
|
||||
std::vector<Layer*> layers;
|
||||
};
|
||||
|
||||
SceneUpdateContext(std::string debug_label,
|
||||
fuchsia::ui::views::ViewToken view_token,
|
||||
scenic::ViewRefPair view_ref_pair,
|
||||
SessionWrapper& session);
|
||||
~SceneUpdateContext() = default;
|
||||
|
||||
scenic::Session* session() { return session_; }
|
||||
|
||||
Entity* top_entity() { return top_entity_; }
|
||||
|
||||
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);
|
||||
|
||||
SessionWrapper& session_;
|
||||
|
||||
scenic::View root_view_;
|
||||
scenic::EntityNode root_node_;
|
||||
|
||||
std::vector<PaintTask> paint_tasks_;
|
||||
|
||||
Entity* top_entity_ = nullptr;
|
||||
float top_scale_x_ = 1.f;
|
||||
float top_scale_y_ = 1.f;
|
||||
float top_elevation_ = 0.f;
|
||||
|
||||
scenic::Session* const session_;
|
||||
SurfaceProducer* const surface_producer_;
|
||||
|
||||
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.
|
||||
|
||||
float alpha_ = 1.0f;
|
||||
float scenic_elevation_ = 0.f;
|
||||
float topmost_global_scenic_elevation_ = kScenicZElevationBetweenLayers;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
session_connection_.Present(this);
|
||||
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();
|
||||
}
|
||||
|
||||
{
|
||||
// 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) {}
|
||||
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::OnSessionMetricsDidChange(
|
||||
const fuchsia::ui::gfx::Metrics& metrics) {
|
||||
session_connection_.set_metrics(metrics);
|
||||
}
|
||||
|
||||
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_) {
|
||||
void Engine::DebugWireframeSettingsChanged(bool enabled) {
|
||||
if (!shell_ || !scene_update_context_) {
|
||||
return;
|
||||
}
|
||||
|
||||
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
|
||||
[rasterizer = shell_->GetRasterizer(), metrics]() {
|
||||
if (rasterizer) {
|
||||
auto compositor_context =
|
||||
reinterpret_cast<flutter_runner::CompositorContext*>(
|
||||
rasterizer->compositor_context());
|
||||
[this, enabled]() { scene_update_context_->EnableWireframe(enabled); });
|
||||
}
|
||||
|
||||
compositor_context->OnSessionMetricsDidChange(metrics);
|
||||
}
|
||||
void Engine::CreateView(int64_t view_id, bool hit_testable, bool focusable) {
|
||||
if (!shell_ || !scene_update_context_) {
|
||||
return;
|
||||
}
|
||||
|
||||
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
|
||||
[this, view_id, hit_testable, focusable]() {
|
||||
scene_update_context_->CreateView(view_id, hit_testable, focusable);
|
||||
});
|
||||
}
|
||||
|
||||
void Engine::OnDebugWireframeSettingsChanged(bool enabled) {
|
||||
if (!shell_) {
|
||||
void Engine::DestroyView(int64_t view_id) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Engine::OnCreateView(int64_t view_id, bool hit_testable, bool focusable) {
|
||||
if (!shell_) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Engine::OnDestroyView(int64_t view_id) {
|
||||
if (!shell_) {
|
||||
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,31 +59,32 @@ 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_;
|
||||
zx::event vsync_event_;
|
||||
fml::WeakPtrFactory<Engine> weak_factory_;
|
||||
// A stub for the FIDL protocol fuchsia.intl.PropertyProvider.
|
||||
|
||||
fuchsia::intl::PropertyProviderPtr intl_property_provider_;
|
||||
|
||||
zx::event vsync_event_;
|
||||
|
||||
fml::WeakPtrFactory<Engine> weak_factory_;
|
||||
|
||||
void OnMainIsolateStart();
|
||||
|
||||
void OnMainIsolateShutdown();
|
||||
|
||||
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();
|
||||
|
||||
|
||||
@ -1,150 +0,0 @@
|
||||
# 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);
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user