Surface frame number identifier through window (flutter/engine#26785)

This commit is contained in:
Jonah Williams 2021-06-28 10:16:01 -07:00 committed by GitHub
parent 4ae3981290
commit ccae44ffd0
17 changed files with 121 additions and 15 deletions

View File

@ -317,6 +317,11 @@ void hooksTests() {
}
}
void expectNotEquals(Object? value, Object? expected) {
if (value == expected) {
throw 'Expected $value to not be $expected.';
}
}
test('onMetricsChanged preserves callback zone', () {
late Zone originalZone;
@ -479,7 +484,7 @@ void hooksTests() {
};
});
_callHook('_beginFrame', 1, 1234);
_callHook('_beginFrame', 2, 1234, 1);
expectIdentical(runZone, innerZone);
expectEquals(start, const Duration(microseconds: 1234));
});
@ -625,6 +630,25 @@ void hooksTests() {
expectEquals(platformBrightness, Brightness.dark);
});
test('onFrameDataChanged preserves callback zone', () {
late Zone innerZone;
late Zone runZone;
late int frameNumber;
runZoned(() {
innerZone = Zone.current;
window.onFrameDataChanged = () {
runZone = Zone.current;
frameNumber = window.frameData.frameNumber;
};
});
_callHook('_beginFrame', 2, 0, 2);
expectNotEquals(runZone, null);
expectIdentical(runZone, innerZone);
expectEquals(frameNumber, 2);
});
_finish();
}

View File

@ -110,8 +110,9 @@ void _dispatchSemanticsAction(int id, int action, ByteData? args) {
@pragma('vm:entry-point')
// ignore: unused_element
void _beginFrame(int microseconds) {
void _beginFrame(int microseconds, int frameNumber) {
PlatformDispatcher.instance._beginFrame(microseconds);
PlatformDispatcher.instance._updateFrameData(frameNumber);
}
@pragma('vm:entry-point')

View File

@ -877,6 +877,29 @@ class PlatformDispatcher {
_onSemanticsActionZone = Zone.current;
}
// Called from the engine via hooks.dart.
void _updateFrameData(int frameNumber) {
final FrameData previous = _frameData;
if (previous.frameNumber == frameNumber) {
return;
}
_frameData = FrameData._(frameNumber: frameNumber);
_invoke(onFrameDataChanged, _onFrameDataChangedZone);
}
/// The [FrameData] object for the current frame.
FrameData get frameData => _frameData;
FrameData _frameData = const FrameData._();
/// A callback that is invoked when the window updates the [FrameData].
VoidCallback? get onFrameDataChanged => _onFrameDataChanged;
VoidCallback? _onFrameDataChanged;
Zone _onFrameDataChangedZone = Zone.root;
set onFrameDataChanged(VoidCallback? callback) {
_onFrameDataChanged = callback;
_onFrameDataChangedZone = Zone.current;
}
// Called from the engine, via hooks.dart
void _dispatchSemanticsAction(int id, int action, ByteData? args) {
_invoke3<int, SemanticsAction, ByteData?>(

View File

@ -633,6 +633,15 @@ class SingletonFlutterWindow extends FlutterWindow {
platformDispatcher.onSemanticsEnabledChanged = callback;
}
/// The [FrameData] object for the current frame.
FrameData get frameData => platformDispatcher.frameData;
/// A callback that is invoked when the window updates the [FrameData].
VoidCallback? get onFrameDataChanged => platformDispatcher.onFrameDataChanged;
set onFrameDataChanged(VoidCallback? callback) {
platformDispatcher.onFrameDataChanged = callback;
}
/// A callback that is invoked whenever the user requests an action to be
/// performed.
///
@ -849,3 +858,16 @@ enum Brightness {
/// belonging to the application, including top level application windows like
/// this one.
final SingletonFlutterWindow window = SingletonFlutterWindow._(0, PlatformDispatcher.instance);
/// Additional data available on each flutter frame.
class FrameData {
const FrameData._({this.frameNumber = -1});
/// The number of the current frame.
///
/// This number monotonically increases, but doesn't necessarily
/// start at a particular value.
///
/// If not provided, defaults to -1.
final int frameNumber;
}

View File

@ -366,7 +366,8 @@ uint64_t PlatformConfiguration::RegisterKeyDataResponse(
return response_id;
}
void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime) {
void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime,
uint64_t frame_number) {
std::shared_ptr<tonic::DartState> dart_state =
begin_frame_.dart_state().lock();
if (!dart_state) {
@ -379,6 +380,7 @@ void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime) {
tonic::LogIfError(
tonic::DartInvoke(begin_frame_.Get(), {
Dart_NewInteger(microseconds),
Dart_NewInteger(frame_number),
}));
UIDartState::Current()->FlushMicrotasksNow();

View File

@ -364,7 +364,12 @@ class PlatformConfiguration final {
/// began. May be used by animation interpolators,
/// physics simulations, etc..
///
void BeginFrame(fml::TimePoint frame_time);
/// @param[in] frame_number The frame number recorded by the animator. Used
/// by the framework to associate frame specific
/// debug information with frame timings and timeline
/// events.
///
void BeginFrame(fml::TimePoint frame_time, uint64_t frame_number);
//----------------------------------------------------------------------------
/// @brief Dart code cannot fully measure the time it takes for a

View File

@ -941,6 +941,8 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
}
});
}
ui.FrameData get frameData => const ui.FrameData.webOnly();
}
bool _handleWebTestEnd2EndMessage(MethodCodec codec, ByteData? data) {

View File

@ -98,6 +98,11 @@ abstract class PlatformDispatcher {
set onSemanticsAction(SemanticsActionCallback? callback);
String get defaultRouteName;
FrameData get frameData;
VoidCallback? get onFrameDataChanged => null;
set onFrameDataChanged(VoidCallback? callback) {}
}
class PlatformConfiguration {

View File

@ -102,6 +102,11 @@ abstract class SingletonFlutterWindow extends FlutterWindow {
platformDispatcher.onSemanticsAction = callback;
}
FrameData get frameData => const FrameData._();
VoidCallback? get onFrameDataChanged => null;
set onFrameDataChanged(VoidCallback? callback) {}
AccessibilityFeatures get accessibilityFeatures => platformDispatcher.accessibilityFeatures;
VoidCallback? get onAccessibilityFeaturesChanged =>
@ -241,3 +246,11 @@ class IsolateNameServer {
}
SingletonFlutterWindow get window => engine.window;
class FrameData {
const FrameData._({this.frameNumber = -1});
const FrameData.webOnly() : frameNumber = -1;
final int frameNumber;
}

View File

@ -177,9 +177,10 @@ bool RuntimeController::SetAccessibilityFeatures(int32_t flags) {
return false;
}
bool RuntimeController::BeginFrame(fml::TimePoint frame_time) {
bool RuntimeController::BeginFrame(fml::TimePoint frame_time,
uint64_t frame_number) {
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
platform_configuration->BeginFrame(frame_time);
platform_configuration->BeginFrame(frame_time, frame_number);
return true;
}

View File

@ -244,7 +244,7 @@ class RuntimeController : public PlatformConfigurationClient {
/// @return If notification to begin frame rendering was delivered to the
/// running isolate.
///
bool BeginFrame(fml::TimePoint frame_time);
bool BeginFrame(fml::TimePoint frame_time, uint64_t frame_number);
//----------------------------------------------------------------------------
/// @brief Dart code cannot fully measure the time it takes for a

View File

@ -149,7 +149,8 @@ void Animator::BeginFrame(
{
TRACE_EVENT2("flutter", "Framework Workload", "mode", "basic", "frame",
FrameParity());
delegate_.OnAnimatorBeginFrame(frame_target_time);
uint64_t frame_number = frame_timings_recorder_->GetFrameNumber();
delegate_.OnAnimatorBeginFrame(frame_target_time, frame_number);
}
if (!frame_scheduled_) {

View File

@ -31,7 +31,8 @@ class Animator final {
public:
class Delegate {
public:
virtual void OnAnimatorBeginFrame(fml::TimePoint frame_target_time) = 0;
virtual void OnAnimatorBeginFrame(fml::TimePoint frame_target_time,
uint64_t frame_number) = 0;
virtual void OnAnimatorNotifyIdle(int64_t deadline) = 0;

View File

@ -220,9 +220,9 @@ Engine::RunStatus Engine::Run(RunConfiguration configuration) {
return Engine::RunStatus::Success;
}
void Engine::BeginFrame(fml::TimePoint frame_time) {
void Engine::BeginFrame(fml::TimePoint frame_time, uint64_t frame_number) {
TRACE_EVENT0("flutter", "Engine::BeginFrame");
runtime_controller_->BeginFrame(frame_time);
runtime_controller_->BeginFrame(frame_time, frame_number);
}
void Engine::ReportTimings(std::vector<int64_t> timings) {

View File

@ -500,7 +500,11 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
/// began. May be used by animation interpolators,
/// physics simulations, etc..
///
void BeginFrame(fml::TimePoint frame_time);
/// @param[in] frame_number The frame number recorded by the animator. Used
/// by the framework to associate frame specific
/// debug information with frame timings and timeline
/// events.
void BeginFrame(fml::TimePoint frame_time, uint64_t frame_number);
//----------------------------------------------------------------------------
/// @brief Notifies the engine that the UI task runner is not expected to

View File

@ -1101,7 +1101,8 @@ void Shell::OnPlatformViewSetNextFrameCallback(const fml::closure& closure) {
}
// |Animator::Delegate|
void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_target_time) {
void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_target_time,
uint64_t frame_number) {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
@ -1111,7 +1112,7 @@ void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_target_time) {
latest_frame_target_time_.emplace(frame_target_time);
}
if (engine_) {
engine_->BeginFrame(frame_target_time);
engine_->BeginFrame(frame_target_time, frame_number);
}
}

View File

@ -532,7 +532,8 @@ class Shell final : public PlatformView::Delegate,
AssetResolver::AssetResolverType type) override;
// |Animator::Delegate|
void OnAnimatorBeginFrame(fml::TimePoint frame_target_time) override;
void OnAnimatorBeginFrame(fml::TimePoint frame_target_time,
uint64_t frame_number) override;
// |Animator::Delegate|
void OnAnimatorNotifyIdle(int64_t deadline) override;