Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,8 @@ ORIGIN: ../../../flutter/shell/common/thread_host.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/variable_refresh_rate_display.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/variable_refresh_rate_display.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/variable_refresh_rate_reporter.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/viewport_metrics_updater.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/viewport_metrics_updater.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/vsync_waiter.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/vsync_waiter.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/common/vsync_waiter_fallback.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -4804,6 +4806,8 @@ FILE: ../../../flutter/shell/common/thread_host.h
FILE: ../../../flutter/shell/common/variable_refresh_rate_display.cc
FILE: ../../../flutter/shell/common/variable_refresh_rate_display.h
FILE: ../../../flutter/shell/common/variable_refresh_rate_reporter.h
FILE: ../../../flutter/shell/common/viewport_metrics_updater.cc
FILE: ../../../flutter/shell/common/viewport_metrics_updater.h
FILE: ../../../flutter/shell/common/vsync_waiter.cc
FILE: ../../../flutter/shell/common/vsync_waiter.h
FILE: ../../../flutter/shell/common/vsync_waiter_fallback.cc
Expand Down
2 changes: 2 additions & 0 deletions shell/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ source_set("common") {
"switches.h",
"thread_host.cc",
"thread_host.h",
"viewport_metrics_updater.cc",
"viewport_metrics_updater.h",
"vsync_waiter.cc",
"vsync_waiter.h",
"vsync_waiter_fallback.cc",
Expand Down
27 changes: 27 additions & 0 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "flutter/shell/common/animator.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/viewport_metrics_updater.h"
#include "rapidjson/document.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"

Expand Down Expand Up @@ -58,6 +59,8 @@ Engine::Engine(
task_runners_(task_runners),
weak_factory_(this) {
pointer_data_dispatcher_ = dispatcher_maker(*this);
viewport_metrics_updater_ = std::unique_ptr<ViewportMetricsUpdater>(
new ViewportMetricsUpdater(*this));
}

Engine::Engine(Delegate& delegate,
Expand Down Expand Up @@ -287,6 +290,30 @@ tonic::DartErrorHandleType Engine::GetUIIsolateLastError() {
}

void Engine::SetViewportMetrics(const ViewportMetrics& metrics) {
viewport_metrics_updater_->UpdateViewportMetrics(metrics);
}

VsyncWaiterProcessStage Engine::GetVsyncWaiterProcessStage() {
std::shared_ptr<VsyncWaiter> waiter = animator_->GetVsyncWaiter().lock();
if (!waiter) {
return VsyncWaiterProcessStage::kProcessingComplete;
}
return waiter->GetProcessStage();
}

fml::TimePoint Engine::GetVsyncWaiterFrameTargetTime() {
std::shared_ptr<VsyncWaiter> waiter = animator_->GetVsyncWaiter().lock();
if (!waiter) {
return fml::TimePoint::Now();
}
return waiter->GetVsyncFrameTargetTime();
}

void Engine::PostTaskOnUITaskRunner(const fml::closure& callback) {
task_runners_.GetUITaskRunner()->PostTask(callback);
}

void Engine::DoUpdateViewportMetrics(const ViewportMetrics& metrics) {
runtime_controller_->SetViewportMetrics(metrics);
ScheduleFrame();
}
Expand Down
21 changes: 19 additions & 2 deletions shell/common/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/run_configuration.h"
#include "flutter/shell/common/shell_io_manager.h"
#include "flutter/shell/common/viewport_metrics_updater.h"
#include "third_party/skia/include/core/SkPicture.h"

namespace flutter {
Expand Down Expand Up @@ -72,7 +73,9 @@ namespace flutter {
/// name and it does happen to be one of the older classes in the
/// repository.
///
class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
class Engine final : public RuntimeDelegate,
PointerDataDispatcher::Delegate,
ViewportMetricsUpdater::Delegate {
public:
//----------------------------------------------------------------------------
/// @brief Indicates the result of the call to `Engine::Run`.
Expand Down Expand Up @@ -795,10 +798,22 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
void DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet,
uint64_t trace_flow_id) override;

// |PointerDataDispatcher::Delegate|
// |PointerDataDispatcher::Delegate|, |ViewportMetricsUpdater::Delegate|
void ScheduleSecondaryVsyncCallback(uintptr_t id,
const fml::closure& callback) override;

// |ViewportMetricsUpdater::Delegate|
void DoUpdateViewportMetrics(const ViewportMetrics& metrics) override;

// |ViewportMetricsUpdater::Delegate|
VsyncWaiterProcessStage GetVsyncWaiterProcessStage() override;

// |ViewportMetricsUpdater::Delegate|
fml::TimePoint GetVsyncWaiterFrameTargetTime() override;

// |ViewportMetricsUpdater::Delegate|
void PostTaskOnUITaskRunner(const fml::closure& callback) override;

//----------------------------------------------------------------------------
/// @brief Get the last Entrypoint that was used in the RunConfiguration
/// when |Engine::Run| was called.
Expand Down Expand Up @@ -958,6 +973,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
// is destructed first.
std::unique_ptr<PointerDataDispatcher> pointer_data_dispatcher_;

std::unique_ptr<ViewportMetricsUpdater> viewport_metrics_updater_;

std::string last_entry_point_;
std::string last_entry_point_library_;
std::vector<std::string> last_entry_point_args_;
Expand Down
65 changes: 65 additions & 0 deletions shell/common/viewport_metrics_updater.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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.

#include "flutter/shell/common/viewport_metrics_updater.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/common/vsync_waiter.h"

namespace flutter {

ViewportMetricsUpdater::ViewportMetricsUpdater(Delegate& delegate)
: delegate_(delegate), weak_factory_(this) {}
ViewportMetricsUpdater::~ViewportMetricsUpdater() = default;

void ViewportMetricsUpdater::UpdateViewportMetrics(
const ViewportMetrics& metrics) {
TRACE_EVENT0("flutter", "ViewportMetricsUpdater::UpdateViewportMetrics");
if (!has_set_valid_viewport_metrics_) {
if (metrics.physical_width > 0 && metrics.physical_height > 0) {
has_set_valid_viewport_metrics_ = true;
delegate_.DoUpdateViewportMetrics(metrics);
}
return;
}

VsyncWaiterProcessStage stage = delegate_.GetVsyncWaiterProcessStage();
switch (stage) {
case VsyncWaiterProcessStage::kAwaiting: {
fml::TimePoint frame_target_time =
delegate_.GetVsyncWaiterFrameTargetTime();
if (frame_target_time > fml::TimePoint::Now()) {
delegate_.DoUpdateViewportMetrics(metrics);
} else {
TRACE_EVENT0("flutter",
"ViewportMetricsUpdaterScheduleSecondaryVsyncCallback");
delegate_.ScheduleSecondaryVsyncCallback(
reinterpret_cast<uintptr_t>(this),
[updater = weak_factory_.GetWeakPtr(), metrics] {
if (updater) {
updater->delegate_.DoUpdateViewportMetrics(metrics);
}
});
}
break;
}
case VsyncWaiterProcessStage::kProcessing: {
TRACE_EVENT0("flutter",
"ViewportMetricsUpdaterRegisterTaskOnUITaskRunner");
delegate_.PostTaskOnUITaskRunner(
[updater = weak_factory_.GetWeakPtr(), metrics]() {
if (updater) {
TRACE_EVENT0("flutter", "UpdateViewportMetricsUsingPostUITask");
updater->delegate_.DoUpdateViewportMetrics(metrics);
}
});
break;
}
case VsyncWaiterProcessStage::kProcessingComplete: {
delegate_.DoUpdateViewportMetrics(metrics);
break;
}
}
}

} // namespace flutter
61 changes: 61 additions & 0 deletions shell/common/viewport_metrics_updater.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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.

#ifndef FLUTTER_VIEWPORT_METRICS_UPDATER_H
#define FLUTTER_VIEWPORT_METRICS_UPDATER_H

#include <memory>
#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "flutter/shell/common/vsync_waiter.h"

namespace flutter {

class ViewportMetricsUpdater;

class ViewportMetricsUpdater {
public:
class Delegate {
public:
/// Actually update the metrics data using Engine's `runtime_controller_`.
virtual void DoUpdateViewportMetrics(const ViewportMetrics& metrics) = 0;

/// Get current process stage of current vsync waiter. And updater will use
/// different strategies to update the viewport metrics data to receiver.
virtual VsyncWaiterProcessStage GetVsyncWaiterProcessStage() = 0;

/// Get current vsync waiter's frame target time.
virtual fml::TimePoint GetVsyncWaiterFrameTargetTime() = 0;

/// Post a task to UI TaskRunner.
virtual void PostTaskOnUITaskRunner(const fml::closure& callback) = 0;

/// Schedule secondary vsync callback to execute after the main vsync
/// process callback.
virtual void ScheduleSecondaryVsyncCallback(
uintptr_t id,
const fml::closure& callback) = 0;
};

explicit ViewportMetricsUpdater(Delegate& delegate);

~ViewportMetricsUpdater();

void UpdateViewportMetrics(const ViewportMetrics& metrics);

private:
Delegate& delegate_;

bool has_set_valid_viewport_metrics_ = false;

// WeakPtrFactory must be the last member.
fml::WeakPtrFactory<ViewportMetricsUpdater> weak_factory_;
FML_DISALLOW_COPY_AND_ASSIGN(ViewportMetricsUpdater);
};

} // namespace flutter

#endif // FLUTTER_VIEWPORT_METRICS_UPDATER_H
62 changes: 58 additions & 4 deletions shell/common/vsync_waiter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#include "flutter/shell/common/vsync_waiter.h"

#include "flow/frame_timings.h"
#include "flutter/fml/task_runner.h"
#include "flutter/fml/trace_event.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "fml/logging.h"
#include "fml/message_loop_task_queues.h"
#include "fml/task_queue_id.h"
Expand All @@ -19,9 +19,30 @@ static constexpr const char* kVsyncFlowName = "VsyncFlow";
static constexpr const char* kVsyncTraceName = "VsyncProcessCallback";

VsyncWaiter::VsyncWaiter(const TaskRunners& task_runners)
: task_runners_(task_runners) {}
: task_runners_(task_runners) {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable([this, &latch]() mutable {
weak_factory_on_ui_ = nullptr;
weak_factory_on_ui_ =
std::make_unique<fml::WeakPtrFactory<VsyncWaiter>>(this);
latch.Signal();
}));
latch.Wait();
}

VsyncWaiter::~VsyncWaiter() = default;
VsyncWaiter::~VsyncWaiter() {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable([weak_factory_on_ui_ = std::move(weak_factory_on_ui_),
&latch]() mutable {
weak_factory_on_ui_.reset();
latch.Signal();
}));
latch.Wait();
};

// Public method invoked by the animator.
void VsyncWaiter::AsyncWaitForVsync(const Callback& callback) {
Expand All @@ -48,6 +69,7 @@ void VsyncWaiter::AsyncWaitForVsync(const Callback& callback) {
}
}
AwaitVSync();
SetProcessStage(VsyncWaiterProcessStage::kAwaiting);
}

void VsyncWaiter::ScheduleSecondaryCallback(uintptr_t id,
Expand Down Expand Up @@ -82,6 +104,17 @@ void VsyncWaiter::ScheduleSecondaryCallback(uintptr_t id,
}
}
AwaitVSyncForSecondaryCallback();
SetProcessStage(VsyncWaiterProcessStage::kAwaiting);
}

VsyncWaiterProcessStage VsyncWaiter::GetProcessStage() {
std::scoped_lock lock(stage_mutex_);
return stage_;
}

fml::TimePoint VsyncWaiter::GetVsyncFrameTargetTime() {
std::scoped_lock lock(frame_target_time_mutex_);
return frame_target_time_;
}

void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time,
Expand All @@ -101,11 +134,15 @@ void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time,
secondary_callbacks_.clear();
}

SetProcessStage(VsyncWaiterProcessStage::kProcessing);
SetFrameTargetTime(frame_target_time);

if (!callback && secondary_callbacks.empty()) {
// This means that the vsync waiter implementation fired a callback for a
// request we did not make. This is a paranoid check but we still want to
// make sure we catch misbehaving vsync implementations.
TRACE_EVENT_INSTANT0("flutter", "MismatchedFrameCallback");
SetProcessStage(VsyncWaiterProcessStage::kProcessingComplete);
return;
}

Expand Down Expand Up @@ -146,6 +183,23 @@ void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time,
for (auto& secondary_callback : secondary_callbacks) {
task_runners_.GetUITaskRunner()->PostTask(secondary_callback);
}

task_runners_.GetUITaskRunner()->PostTask(
[waiter = weak_factory_on_ui_->GetWeakPtr()] {
if (waiter) {
waiter->SetProcessStage(VsyncWaiterProcessStage::kProcessingComplete);
}
});
}

void VsyncWaiter::SetProcessStage(VsyncWaiterProcessStage stage) {
std::scoped_lock lock(stage_mutex_);
stage_ = stage;
}

void VsyncWaiter::SetFrameTargetTime(fml::TimePoint frame_target_time) {
std::scoped_lock lock(frame_target_time_mutex_);
frame_target_time_ = frame_target_time;
}

void VsyncWaiter::PauseDartMicroTasks() {
Expand Down
Loading