Skip to content

Commit

Permalink
Use metrics provided by scene events. (flutter#3922)
Browse files Browse the repository at this point in the history
Compute the necessary texture resolution using more accurate scaling
information provided by Mozart scene node metrics events instead of the
device pixel ratio provided by the Mozart view properties (which we
might remove in the future).

This allows us to allocate smaller textures when a Flutter view is
being scaled down.
  • Loading branch information
Jeff Brown authored Jul 25, 2017
1 parent 3a12bc0 commit 8ee1910
Show file tree
Hide file tree
Showing 20 changed files with 216 additions and 133 deletions.
6 changes: 4 additions & 2 deletions content_handler/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ class Rasterizer {

static std::unique_ptr<Rasterizer> Create();

virtual void SetSession(fidl::InterfaceHandle<mozart2::Session> session,
mx::eventpair import_token) = 0;
virtual void SetScene(
fidl::InterfaceHandle<mozart2::SceneManager> scene_manager,
mx::eventpair import_token,
ftl::Closure metrics_changed_callback) = 0;

virtual void Draw(std::unique_ptr<flow::LayerTree> layer_tree,
ftl::Closure callback) = 0;
Expand Down
60 changes: 44 additions & 16 deletions content_handler/runtime_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,36 @@ void RuntimeHolder::CreateView(
input_connection_->SetEventListener(std::move(input_listener));

// Setup the session.
mozart2::SessionPtr session;
mozart2::SceneManagerPtr scene_manager;
fidl::InterfaceHandle<mozart2::SceneManager> scene_manager;
view_manager_->GetSceneManager(scene_manager.NewRequest());
scene_manager->CreateSession(session.NewRequest(),
nullptr /* session listener */);

blink::Threads::Gpu()->PostTask(ftl::MakeCopyable([
rasterizer = rasterizer_.get(), //
session = session.PassInterfaceHandle(), //
import_token = std::move(import_token) //
rasterizer = rasterizer_.get(), //
scene_manager = std::move(scene_manager), //
import_token = std::move(import_token), //
weak_runtime_holder = GetWeakPtr()
]() mutable {
ASSERT_IS_GPU_THREAD;
rasterizer->SetSession(std::move(session), std::move(import_token));
rasterizer->SetScene(
std::move(scene_manager), std::move(import_token),
// TODO(MZ-222): Ideally we would immediately redraw the previous layer
// tree when the metrics change since there's no need to rerecord it.
// However, we want to make sure there's only one outstanding frame.
// We should improve the frame scheduling so that the rasterizer thread
// can self-schedule re-rasterization.
[weak_runtime_holder] {
// This is on the GPU thread thread. Post to the Platform/UI
// thread for the completion callback.
ASSERT_IS_GPU_THREAD;
blink::Threads::Platform()->PostTask([weak_runtime_holder]() {
// On the Platform/UI thread.
ASSERT_IS_UI_THREAD;
if (weak_runtime_holder) {
weak_runtime_holder->OnRedrawFrame();
}
});
});
}));

runtime_ = blink::RuntimeController::Create(this);

const uint8_t* isolate_snapshot_data;
Expand Down Expand Up @@ -290,6 +306,7 @@ void RuntimeHolder::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
last_begin_frame_time_);
layer_tree->set_frame_size(SkISize::Make(viewport_metrics_.physical_width,
viewport_metrics_.physical_height));
layer_tree->set_device_pixel_ratio(viewport_metrics_.device_pixel_ratio);

// We are on the Platform/UI thread. Post to the GPU thread to render.
ASSERT_IS_PLATFORM_THREAD;
Expand All @@ -301,8 +318,8 @@ void RuntimeHolder::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
// On the GPU Thread.
ASSERT_IS_GPU_THREAD;
rasterizer->Draw(std::move(layer_tree), [weak_runtime_holder]() {
// This is on the GPU thread thread. Post to the Platform/UI thread for
// the completion callback.
// This is on the GPU thread thread. Post to the Platform/UI thread
// for the completion callback.
ASSERT_IS_GPU_THREAD;
blink::Threads::Platform()->PostTask([weak_runtime_holder]() {
// On the Platform/UI thread.
Expand Down Expand Up @@ -516,8 +533,8 @@ void RuntimeHolder::OnEvent(mozart::InputEventPtr event,
pointer_data.change = GetChangeFromPointerEventPhase(pointer->phase);
pointer_data.kind = GetKindFromPointerType(pointer->type);
pointer_data.device = pointer->pointer_id;
pointer_data.physical_x = pointer->x;
pointer_data.physical_y = pointer->y;
pointer_data.physical_x = pointer->x * viewport_metrics_.device_pixel_ratio;
pointer_data.physical_y = pointer->y * viewport_metrics_.device_pixel_ratio;

switch (pointer_data.change) {
case blink::PointerData::Change::kDown:
Expand Down Expand Up @@ -585,15 +602,21 @@ void RuntimeHolder::OnPropertiesChanged(
FTL_DCHECK(properties);

// Attempt to read the device pixel ratio.
float pixel_ratio = 1.0;
float pixel_ratio = 1.f;
if (auto& metrics = properties->display_metrics) {
pixel_ratio = metrics->device_pixel_ratio;
}

// Apply view property changes.
if (auto& layout = properties->view_layout) {
viewport_metrics_.physical_width = layout->size->width;
viewport_metrics_.physical_height = layout->size->height;
viewport_metrics_.physical_width = layout->size->width * pixel_ratio;
viewport_metrics_.physical_height = layout->size->height * pixel_ratio;
viewport_metrics_.physical_padding_top = layout->inset->top * pixel_ratio;
viewport_metrics_.physical_padding_right =
layout->inset->right * pixel_ratio;
viewport_metrics_.physical_padding_bottom =
layout->inset->bottom * pixel_ratio;
viewport_metrics_.physical_padding_left = layout->inset->left * pixel_ratio;
viewport_metrics_.device_pixel_ratio = pixel_ratio;
runtime_->SetViewportMetrics(viewport_metrics_);
}
Expand Down Expand Up @@ -706,4 +729,9 @@ void RuntimeHolder::OnFrameComplete() {
PostBeginFrame();
}

void RuntimeHolder::OnRedrawFrame() {
if (!frame_outstanding_)
ScheduleFrame();
}

} // namespace flutter_runner
1 change: 1 addition & 0 deletions content_handler/runtime_holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class RuntimeHolder : public blink::RuntimeDelegate,
void PostBeginFrame();
void BeginFrame();
void OnFrameComplete();
void OnRedrawFrame();
void Invalidate();

std::unique_ptr<app::ApplicationContext> context_;
Expand Down
35 changes: 30 additions & 5 deletions content_handler/session_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@

namespace flutter_runner {

SessionConnection::SessionConnection(
fidl::InterfaceHandle<mozart2::Session> session_handle,
mx::eventpair import_token)
: session_(mozart2::SessionPtr::Create(std::move(session_handle))),
SessionConnection::SessionConnection(mozart2::SceneManagerPtr scene_manager,
mx::eventpair import_token)
: session_(scene_manager.get()),
root_node_(&session_),
surface_producer_(std::make_unique<VulkanSurfaceProducer>(&session_)),
scene_update_context_(&session_, surface_producer_.get()) {
ASSERT_IS_GPU_THREAD;
root_node_.Bind(std::move(import_token));

session_.set_connection_error_handler(
std::bind(&SessionConnection::OnSessionError, this));
session_.set_event_handler(std::bind(&SessionConnection::OnSessionEvents,
this, std::placeholders::_1,
std::placeholders::_2));

root_node_.Bind(std::move(import_token));
root_node_.SetEventMask(mozart2::kMetricsEventMask);
session_.Present(0, [](mozart2::PresentationInfoPtr info) {});

present_callback_ =
std::bind(&SessionConnection::OnPresent, this, std::placeholders::_1);
}
Expand All @@ -32,6 +39,24 @@ void SessionConnection::OnSessionError() {
FTL_CHECK(false) << "Session connection was terminated.";
}

void SessionConnection::OnSessionEvents(uint64_t presentation_time,
fidl::Array<mozart2::EventPtr> events) {
mozart2::MetricsPtr new_metrics;
for (const auto& event : events) {
if (event->is_metrics() &&
event->get_metrics()->node_id == root_node_.id()) {
new_metrics = std::move(event->get_metrics()->metrics);
}
}
if (!new_metrics)
return;

scene_update_context_.set_metrics(std::move(new_metrics));

if (metrics_changed_callback_)
metrics_changed_callback_();
}

void SessionConnection::Present(flow::CompositorContext::ScopedFrame& frame,
ftl::Closure on_present_callback) {
ASSERT_IS_GPU_THREAD;
Expand Down
12 changes: 11 additions & 1 deletion content_handler/session_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,25 @@
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/scene_update_context.h"
#include "lib/fidl/cpp/bindings/interface_handle.h"
#include "lib/ftl/functional/closure.h"
#include "lib/ftl/macros.h"
#include "magenta/system/ulib/mx/include/mx/eventpair.h"

namespace flutter_runner {

class SessionConnection {
public:
SessionConnection(fidl::InterfaceHandle<mozart2::Session> session_handle,
SessionConnection(mozart2::SceneManagerPtr scene_manager,
mx::eventpair import_token);

~SessionConnection();

bool has_metrics() const { return scene_update_context_.has_metrics(); }

void set_metrics_changed_callback(ftl::Closure callback) {
metrics_changed_callback_ = std::move(callback);
}

flow::SceneUpdateContext& scene_update_context() {
return scene_update_context_;
}
Expand All @@ -43,8 +50,11 @@ class SessionConnection {
ftl::Closure pending_on_present_callback_;
std::unique_ptr<VulkanSurfaceProducer> surface_producer_;
flow::SceneUpdateContext scene_update_context_;
ftl::Closure metrics_changed_callback_;

void OnSessionError();
void OnSessionEvents(uint64_t presentation_time,
fidl::Array<mozart2::EventPtr> events);

void EnqueueClearOps();

Expand Down
18 changes: 14 additions & 4 deletions content_handler/vulkan_rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@ bool VulkanRasterizer::IsValid() const {
return valid_;
}

void VulkanRasterizer::SetSession(
fidl::InterfaceHandle<mozart2::Session> session,
mx::eventpair import_token) {
void VulkanRasterizer::SetScene(
fidl::InterfaceHandle<mozart2::SceneManager> scene_manager,
mx::eventpair import_token,
ftl::Closure metrics_changed_callback) {
ASSERT_IS_GPU_THREAD;
FTL_DCHECK(valid_ && !session_connection_);
session_connection_ = std::make_unique<SessionConnection>(
std::move(session), std::move(import_token));
mozart2::SceneManagerPtr::Create(std::move(scene_manager)),
std::move(import_token));
session_connection_->set_metrics_changed_callback(
std::move(metrics_changed_callback));
}

void VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
Expand All @@ -79,6 +83,12 @@ void VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
return;
}

if (!session_connection_->has_metrics()) {
// Still awaiting metrics. Will redraw when we get them.
callback();
return;
}

compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());

flow::CompositorContext::ScopedFrame frame = compositor_context_.AcquireFrame(
Expand Down
5 changes: 3 additions & 2 deletions content_handler/vulkan_rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ class VulkanRasterizer : public Rasterizer {

bool IsValid() const;

void SetSession(fidl::InterfaceHandle<mozart2::Session> session,
mx::eventpair import_token) override;
void SetScene(fidl::InterfaceHandle<mozart2::SceneManager> scene_manager,
mx::eventpair import_token,
ftl::Closure metrics_changed_callback) override;

void Draw(std::unique_ptr<flow::LayerTree> layer_tree,
ftl::Closure callback) override;
Expand Down
2 changes: 0 additions & 2 deletions flow/export_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ ExportNode::~ExportNode() {
void ExportNode::Bind(SceneUpdateContext& context,
mozart::client::ContainerNode& container,
const SkPoint& offset,
float scale,
bool hit_testable) {
ftl::MutexLocker lock(&mutex_);

Expand All @@ -29,7 +28,6 @@ void ExportNode::Bind(SceneUpdateContext& context,
if (node_) {
container.AddChild(*node_);
node_->SetTranslation(offset.x(), offset.y(), 0.f);
node_->SetScale(scale, scale, 1.f);
node_->SetHitTestBehavior(hit_testable
? mozart2::HitTestBehavior::kDefault
: mozart2::HitTestBehavior::kSuppress);
Expand Down
1 change: 0 additions & 1 deletion flow/export_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class ExportNode : public ftl::RefCountedThreadSafe<ExportNode> {
void Bind(SceneUpdateContext& context,
mozart::client::ContainerNode& container,
const SkPoint& offset,
float scale,
bool hit_testable);

private:
Expand Down
9 changes: 1 addition & 8 deletions flow/layers/child_scene_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,8 @@ void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) {
// or whether we should leave this up to the Flutter application to decide.
// In some situations, it might be useful to allow children to draw
// outside of their layout bounds.
//
// float inverse_device_pixel_ratio = 1.f / device_pixel_ratio_;
// SkRect bounds =
// SkRect::MakeXYWH(offset_.x(), offset_.y(),
// physical_size_.width() * inverse_device_pixel_ratio,
// physical_size_.height() * inverse_device_pixel_ratio);
if (export_node_) {
context.AddChildScene(export_node_.get(), offset_, device_pixel_ratio_,
hit_testable_);
context.AddChildScene(export_node_.get(), offset_, hit_testable_);
}
}

Expand Down
11 changes: 2 additions & 9 deletions flow/layers/child_scene_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ class ChildSceneLayer : public Layer {

void set_offset(const SkPoint& offset) { offset_ = offset; }

void set_device_pixel_ratio(float device_pixel_ratio) {
device_pixel_ratio_ = device_pixel_ratio;
}

void set_physical_size(const SkISize& physical_size) {
physical_size_ = physical_size;
}
void set_size(const SkSize& size) { size_ = size; }

void set_export_node(ftl::RefPtr<ExportNode> export_node) {
export_node_ = std::move(export_node);
Expand All @@ -39,8 +33,7 @@ class ChildSceneLayer : public Layer {

private:
SkPoint offset_;
float device_pixel_ratio_ = 1.0;
SkISize physical_size_;
SkSize size_;
ftl::RefPtr<ExportNode> export_node_;
bool hit_testable_ = true;

Expand Down
9 changes: 6 additions & 3 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
frame.gr_context(), color_space, SkRect::MakeEmpty(),
};

root_layer_->Preroll(&context, SkMatrix::I());
}

Expand All @@ -42,18 +43,20 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
mozart::client::ContainerNode& container) {
TRACE_EVENT0("flutter", "LayerTree::UpdateScene");

SceneUpdateContext::Transform transform(context, 1.f / device_pixel_ratio_,
1.f / device_pixel_ratio_, 1.f);
SceneUpdateContext::Frame frame(
context,
SkRRect::MakeRect(
SkRect::MakeIWH(frame_size_.width(), frame_size_.height())),
SK_ColorTRANSPARENT, 0.f, 1.f, 1.f);
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
SK_ColorTRANSPARENT, 0.f);
if (root_layer_->needs_system_composite()) {
root_layer_->UpdateScene(context);
}
if (root_layer_->needs_painting()) {
frame.AddPaintedLayer(root_layer_.get());
}
container.AddChild(frame.entity_node());
container.AddChild(transform.entity_node());
}
#endif

Expand Down
8 changes: 8 additions & 0 deletions flow/layers/layer_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class LayerTree {
bool ignore_raster_cache = false);

#if defined(OS_FUCHSIA)
void set_device_pixel_ratio(float device_pixel_ratio) {
device_pixel_ratio_ = device_pixel_ratio;
}

void UpdateScene(SceneUpdateContext& context,
mozart::client::ContainerNode& container);
#endif
Expand Down Expand Up @@ -80,6 +84,10 @@ class LayerTree {
bool checkerboard_raster_cache_images_;
bool checkerboard_offscreen_layers_;

#if defined(OS_FUCHSIA)
float device_pixel_ratio_ = 1.f;
#endif

FTL_DISALLOW_COPY_AND_ASSIGN(LayerTree);
};

Expand Down
Loading

0 comments on commit 8ee1910

Please sign in to comment.