From 8d6ded45f0efc77c700762ec92de124cc13aabff Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 27 Apr 2017 10:23:46 -0700 Subject: [PATCH] Add a second per-frame callback that is invoked after the microtask queue is drained (#3632) See https://github.com/flutter/flutter/issues/7626 --- lib/ui/hooks.dart | 5 +++++ lib/ui/window.dart | 6 ++++++ lib/ui/window/window.cc | 5 +++++ runtime/dart_vm_entry_points.txt | 1 + 4 files changed, 17 insertions(+) diff --git a/lib/ui/hooks.dart b/lib/ui/hooks.dart index 94ad415bc0d..b2a481eed5f 100644 --- a/lib/ui/hooks.dart +++ b/lib/ui/hooks.dart @@ -83,6 +83,11 @@ void _beginFrame(int microseconds) { window.onBeginFrame(new Duration(microseconds: microseconds)); } +void _drawFrame() { + if (window.onDrawFrame != null) + window.onDrawFrame(); +} + // If this value changes, update the encoding code in the following files: // // * pointer_data.cc diff --git a/lib/ui/window.dart b/lib/ui/window.dart index 614a597b19a..d56bb9e21a3 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -149,6 +149,12 @@ class Window { /// last time this callback was invoked. FrameCallback onBeginFrame; + /// A callback that is invoked for each frame after onBeginFrame has + /// completed and after the microtask queue has been drained. This can be + /// used to implement a second phase of frame rendering that happens + /// after any deferred work queued by the onBeginFrame phase. + VoidCallback onDrawFrame; + /// A callback that is invoked when pointer data is available. PointerDataPacketCallback onPointerDataPacket; diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 45fc1bce8de..c5ee7e8f511 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -10,6 +10,7 @@ #include "lib/tonic/converter/dart_converter.h" #include "lib/tonic/dart_args.h" #include "lib/tonic/dart_library_natives.h" +#include "lib/tonic/dart_microtask_queue.h" #include "lib/tonic/logging/dart_invoke.h" #include "lib/tonic/typed_data/dart_byte_data.h" @@ -221,6 +222,10 @@ void Window::BeginFrame(ftl::TimePoint frameTime) { { Dart_NewInteger(microseconds), }); + + tonic::DartMicrotaskQueue::RunMicrotasks(); + + DartInvokeField(library_.value(), "_drawFrame", {}); } void Window::CompletePlatformMessageEmptyResponse(int response_id) { diff --git a/runtime/dart_vm_entry_points.txt b/runtime/dart_vm_entry_points.txt index 6eb139015b9..a4ef2430f57 100644 --- a/runtime/dart_vm_entry_points.txt +++ b/runtime/dart_vm_entry_points.txt @@ -5,6 +5,7 @@ dart:isolate,::,_getIsolateScheduleImmediateClosure dart:isolate,::,_setupHooks dart:isolate,::,_startMainIsolate dart:ui,::,_beginFrame +dart:ui,::,_drawFrame dart:ui,::,_dispatchPlatformMessage dart:ui,::,_dispatchPointerDataPacket dart:ui,::,_dispatchSemanticsAction