From 54ee61e60a1da2a1b9ff00a0662a636e445bfdf3 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 24 Oct 2016 16:14:37 -0700 Subject: [PATCH] Migrate vsync away from Mojo services (flutter/engine#3169) Instead, just use JNI and Objective-C directly. --- DEPS | 2 +- engine/src/flutter/shell/common/BUILD.gn | 5 +- engine/src/flutter/shell/common/animator.cc | 45 ++++------- engine/src/flutter/shell/common/animator.h | 27 ++++--- engine/src/flutter/shell/common/engine.cc | 38 +--------- engine/src/flutter/shell/common/engine.h | 9 --- .../src/flutter/shell/common/platform_view.cc | 15 +++- .../src/flutter/shell/common/platform_view.h | 7 ++ .../src/flutter/shell/common/vsync_waiter.cc | 11 +++ .../src/flutter/shell/common/vsync_waiter.h | 25 ++++++ .../shell/common/vsync_waiter_fallback.cc | 51 +++++++++++++ .../shell/common/vsync_waiter_fallback.h | 33 ++++++++ .../flutter/shell/platform/android/BUILD.gn | 5 +- .../android/io/flutter/view/FlutterMain.java | 13 ---- .../android/io/flutter/view/FlutterView.java | 26 ------- .../io/flutter/view/ServiceRegistry.java | 2 - .../android/io/flutter/view/VsyncWaiter.java | 25 ++++++ .../shell/platform/android/library_loader.cc | 2 + .../platform/android/platform_view_android.cc | 11 ++- .../platform/android/platform_view_android.h | 2 + .../platform/android/vsync_waiter_android.cc | 58 ++++++++++++++ .../platform/android/vsync_waiter_android.h | 37 +++++++++ .../shell/platform/darwin/common/BUILD.gn | 3 - .../common/platform_service_provider.cc | 39 ---------- .../darwin/common/platform_service_provider.h | 32 -------- .../shell/platform/darwin/desktop/BUILD.gn | 2 + .../darwin/desktop/platform_view_mac.h | 2 + .../darwin/desktop/platform_view_mac.mm | 17 +++-- .../darwin/desktop/vsync_waiter_mac.cc | 58 ++++++++++++++ .../darwin/desktop/vsync_waiter_mac.h | 33 ++++++++ .../shell/platform/darwin/ios/BUILD.gn | 3 +- .../ios/framework/Source/vsync_waiter_ios.h | 35 +++++++++ .../ios/framework/Source/vsync_waiter_ios.mm | 76 +++++++++++++++++++ .../platform/darwin/ios/platform_view_ios.h | 2 + .../platform/darwin/ios/platform_view_ios.mm | 20 ++--- .../platform/linux/platform_view_glfw.cc | 9 +-- .../shell/testing/platform_view_test.cc | 4 +- 37 files changed, 549 insertions(+), 235 deletions(-) create mode 100644 engine/src/flutter/shell/common/vsync_waiter.cc create mode 100644 engine/src/flutter/shell/common/vsync_waiter.h create mode 100644 engine/src/flutter/shell/common/vsync_waiter_fallback.cc create mode 100644 engine/src/flutter/shell/common/vsync_waiter_fallback.h create mode 100644 engine/src/flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java create mode 100644 engine/src/flutter/shell/platform/android/vsync_waiter_android.cc create mode 100644 engine/src/flutter/shell/platform/android/vsync_waiter_android.h delete mode 100644 engine/src/flutter/shell/platform/darwin/common/platform_service_provider.cc delete mode 100644 engine/src/flutter/shell/platform/darwin/common/platform_service_provider.h create mode 100644 engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.cc create mode 100644 engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.h create mode 100644 engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h create mode 100644 engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm diff --git a/DEPS b/DEPS index 00613ee2227..6b76d67750e 100644 --- a/DEPS +++ b/DEPS @@ -54,7 +54,7 @@ deps = { # and not have to specific specific hashes. 'src/lib/ftl': - Var('fuchsia_git') + '/ftl' + '@' + 'e8d8bf108418d5de96971ecd04b7cc0a58d8a568', + Var('fuchsia_git') + '/ftl' + '@' + '9f51f24056554352b045fda338e9101c0e5af272', 'src/lib/tonic': Var('fuchsia_git') + '/tonic' + '@' + 'e1d221b924cb2a604363a8a9dd393d319becc0e8', diff --git a/engine/src/flutter/shell/common/BUILD.gn b/engine/src/flutter/shell/common/BUILD.gn index 4a5319b9fd8..cee06445e72 100644 --- a/engine/src/flutter/shell/common/BUILD.gn +++ b/engine/src/flutter/shell/common/BUILD.gn @@ -40,6 +40,10 @@ source_set("common") { "switches.h", "tracing_controller.cc", "tracing_controller.h", + "vsync_waiter.cc", + "vsync_waiter.h", + "vsync_waiter_fallback.cc", + "vsync_waiter_fallback.h", ] deps = [ @@ -54,7 +58,6 @@ source_set("common") { "//flutter/lib/ui", "//flutter/runtime", "//flutter/services/engine:interfaces", - "//flutter/services/vsync", "//flutter/skia", "//flutter/sky/engine/wtf", "//flutter/synchronization", diff --git a/engine/src/flutter/shell/common/animator.cc b/engine/src/flutter/shell/common/animator.cc index ddedfc8eb3a..15768fc9737 100644 --- a/engine/src/flutter/shell/common/animator.cc +++ b/engine/src/flutter/shell/common/animator.cc @@ -12,17 +12,16 @@ namespace shell { -Animator::Animator(ftl::WeakPtr rasterizer, Engine* engine) +Animator::Animator(ftl::WeakPtr rasterizer, + VsyncWaiter* waiter, + Engine* engine) : rasterizer_(rasterizer), + waiter_(waiter), engine_(engine), layer_tree_pipeline_(ftl::MakeRefCounted(3)), pending_frame_semaphore_(1), paused_(false), - weak_factory_(this) { - new sky::services::vsync::VsyncProviderFallbackImpl( - mojo::InterfaceRequest<::vsync::VSyncProvider>( - mojo::GetProxy(&fallback_vsync_provider_))); -} + weak_factory_(this) {} Animator::~Animator() = default; @@ -39,7 +38,7 @@ void Animator::Start() { RequestFrame(); } -void Animator::BeginFrame(int64_t time_stamp) { +void Animator::BeginFrame(ftl::TimePoint frame_time) { pending_frame_semaphore_.Signal(); if (!producer_continuation_) { @@ -63,6 +62,8 @@ void Animator::BeginFrame(int64_t time_stamp) { // to service potential frame. DCHECK(producer_continuation_); + // TODO(abarth): We should use |frame_time| instead, but the frame time we get + // on Android appears to be unstable. last_begin_frame_time_ = ftl::TimePoint::Now(); engine_->BeginFrame(last_begin_frame_time_); } @@ -92,7 +93,7 @@ void Animator::RequestFrame() { if (!pending_frame_semaphore_.TryWait()) { // Multiple calls to Animator::RequestFrame will still result in a single - // request to the VSyncProvider. + // request to the VsyncWaiter. return; } @@ -107,30 +108,16 @@ void Animator::RequestFrame() { if (!self.get()) return; TRACE_EVENT_INSTANT0("flutter", "RequestFrame", TRACE_EVENT_SCOPE_PROCESS); - self->AwaitVSync(base::Bind(&Animator::BeginFrame, self)); + self->AwaitVSync(); }); } -void Animator::set_vsync_provider(vsync::VSyncProviderPtr vsync_provider) { - vsync_provider_ = vsync_provider.Pass(); - - // We may be waiting on a VSync signal from the old VSync provider. - pending_frame_semaphore_.Signal(); - - RequestFrame(); -} - -void Animator::AwaitVSync( - const vsync::VSyncProvider::AwaitVSyncCallback& callback) { - // First, try the platform provided VSync provider. - if (vsync_provider_) { - vsync_provider_->AwaitVSync(callback); - return; - } - - // Then, use the fallback provider if the platform cannot reliably supply - // VSync signals to us. - return fallback_vsync_provider_->AwaitVSync(callback); +void Animator::AwaitVSync() { + waiter_->AsyncWaitForVsync([self = weak_factory_.GetWeakPtr()]( + ftl::TimePoint frame_time) { + if (self) + self->BeginFrame(frame_time); + }); } } // namespace shell diff --git a/engine/src/flutter/shell/common/animator.h b/engine/src/flutter/shell/common/animator.h index 107cfa51123..fc84fe62ec0 100644 --- a/engine/src/flutter/shell/common/animator.h +++ b/engine/src/flutter/shell/common/animator.h @@ -2,24 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SHELL_COMMON_ANIMATOR_H_ -#define SHELL_COMMON_ANIMATOR_H_ +#ifndef FLUTTER_SHELL_COMMON_ANIMATOR_H_ +#define FLUTTER_SHELL_COMMON_ANIMATOR_H_ -#include "base/memory/weak_ptr.h" -#include "flutter/services/vsync/fallback/vsync_provider_fallback_impl.h" #include "flutter/shell/common/engine.h" #include "flutter/shell/common/rasterizer.h" +#include "flutter/shell/common/vsync_waiter.h" #include "flutter/synchronization/pipeline.h" #include "flutter/synchronization/semaphore.h" #include "lib/ftl/memory/ref_ptr.h" +#include "lib/ftl/memory/weak_ptr.h" #include "lib/ftl/time/time_point.h" -#include "mojo/services/vsync/interfaces/vsync.mojom.h" namespace shell { class Animator { public: - explicit Animator(ftl::WeakPtr rasterizer, Engine* engine); + Animator(ftl::WeakPtr rasterizer, + VsyncWaiter* waiter, + Engine* engine); ~Animator(); @@ -31,30 +32,28 @@ class Animator { void Stop(); - void set_vsync_provider(vsync::VSyncProviderPtr vsync_provider); - private: using LayerTreePipeline = flutter::Pipeline; - void BeginFrame(int64_t time_stamp); + void BeginFrame(ftl::TimePoint frame_time); - void AwaitVSync(const vsync::VSyncProvider::AwaitVSyncCallback& callback); + void AwaitVSync(); ftl::WeakPtr rasterizer_; + VsyncWaiter* waiter_; Engine* engine_; - vsync::VSyncProviderPtr vsync_provider_; - vsync::VSyncProviderPtr fallback_vsync_provider_; + ftl::TimePoint last_begin_frame_time_; ftl::RefPtr layer_tree_pipeline_; flutter::Semaphore pending_frame_semaphore_; LayerTreePipeline::ProducerContinuation producer_continuation_; bool paused_; - base::WeakPtrFactory weak_factory_; + ftl::WeakPtrFactory weak_factory_; FTL_DISALLOW_COPY_AND_ASSIGN(Animator); }; } // namespace shell -#endif // SHELL_COMMON_ANIMATOR_H_ +#endif // FLUTTER_SHELL_COMMON_ANIMATOR_H_ diff --git a/engine/src/flutter/shell/common/engine.cc b/engine/src/flutter/shell/common/engine.cc index 1dc4bb5b21e..472b0c63a1f 100644 --- a/engine/src/flutter/shell/common/engine.cc +++ b/engine/src/flutter/shell/common/engine.cc @@ -52,8 +52,10 @@ std::string FindPackagesPath(const std::string& main_dart) { Engine::Engine(PlatformView* platform_view) : platform_view_(platform_view->GetWeakPtr()), - animator_(new Animator(platform_view->rasterizer().GetWeakRasterizerPtr(), - this)), + animator_(std::make_unique( + platform_view->rasterizer().GetWeakRasterizerPtr(), + platform_view->GetVsyncWaiter(), + this)), binding_(this), activity_running_(false), have_surface_(false), @@ -119,32 +121,6 @@ void Engine::OnOutputSurfaceDestroyed(const ftl::Closure& gpu_continuation) { blink::Threads::Gpu()->PostTask(gpu_continuation); } -void Engine::SetServices(sky::ServicesDataPtr services) { - services_ = services.Pass(); - - if (services_->incoming_services) { - incoming_services_ = - mojo::ServiceProviderPtr::Create(services_->incoming_services.Pass()); - service_provider_impl_.set_fallback_service_provider( - incoming_services_.get()); - } - - vsync::VSyncProviderPtr vsync_provider; - if (services_->shell) { - // We bind and unbind our Shell here, since this is the only place we - // use - // it in this class. - auto shell = mojo::ShellPtr::Create(services_->shell.Pass()); - mojo::ConnectToService(shell.get(), "mojo:vsync", - mojo::GetProxy(&vsync_provider)); - services_->shell = shell.Pass(); - } else { - mojo::ConnectToService(incoming_services_.get(), - mojo::GetProxy(&vsync_provider)); - } - animator_->set_vsync_provider(vsync_provider.Pass()); -} - void Engine::OnViewportMetricsChanged(sky::ViewportMetricsPtr metrics) { viewport_metrics_ = metrics.Pass(); if (runtime_) @@ -307,12 +283,6 @@ void Engine::DidCreateMainIsolate(Dart_Isolate isolate) { void Engine::DidCreateSecondaryIsolate(Dart_Isolate isolate) {} -void Engine::BindToServiceProvider( - mojo::InterfaceRequest request) { - service_provider_bindings_.AddBinding(&service_provider_impl_, - request.Pass()); -} - void Engine::StopAnimator() { animator_->Stop(); } diff --git a/engine/src/flutter/shell/common/engine.h b/engine/src/flutter/shell/common/engine.h index c7191d6f4f6..ab78cab12ea 100644 --- a/engine/src/flutter/shell/common/engine.h +++ b/engine/src/flutter/shell/common/engine.h @@ -63,7 +63,6 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate { private: // SkyEngine implementation: - void SetServices(sky::ServicesDataPtr services) override; void OnViewportMetricsChanged(sky::ViewportMetricsPtr metrics) override; void OnLocaleChanged(const mojo::String& language_code, const mojo::String& country_code) override; @@ -90,9 +89,6 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate { void DidCreateMainIsolate(Dart_Isolate isolate) override; void DidCreateSecondaryIsolate(Dart_Isolate isolate) override; - void BindToServiceProvider( - mojo::InterfaceRequest request); - void RunFromSnapshotStream(const std::string& script_uri, mojo::ScopedDataPipeConsumerHandle snapshot); @@ -107,11 +103,6 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate { ftl::WeakPtr platform_view_; std::unique_ptr animator_; - sky::ServicesDataPtr services_; - mojo::ServiceProviderImpl service_provider_impl_; - mojo::ServiceProviderPtr incoming_services_; - mojo::BindingSet service_provider_bindings_; - mojo::asset_bundle::AssetBundlePtr root_bundle_; std::unique_ptr runtime_; diff --git a/engine/src/flutter/shell/common/platform_view.cc b/engine/src/flutter/shell/common/platform_view.cc index f1c7944c5de..cef3de79fca 100644 --- a/engine/src/flutter/shell/common/platform_view.cc +++ b/engine/src/flutter/shell/common/platform_view.cc @@ -9,6 +9,7 @@ #include "flutter/common/threads.h" #include "flutter/lib/ui/painting/resource_context.h" #include "flutter/shell/common/rasterizer.h" +#include "flutter/shell/common/vsync_waiter_fallback.h" #include "lib/ftl/functional/make_copyable.h" #include "third_party/skia/include/gpu/gl/GrGLInterface.h" @@ -17,9 +18,7 @@ namespace shell { PlatformView::PlatformView(std::unique_ptr rasterizer) : rasterizer_(std::move(rasterizer)), size_(SkISize::Make(0, 0)), - weak_factory_(this) { - engine_.reset(new Engine(this)); -} + weak_factory_(this) {} PlatformView::~PlatformView() { blink::Threads::UI()->PostTask( @@ -32,6 +31,10 @@ PlatformView::~PlatformView() { blink::Threads::UI()->PostTask([engine]() { delete engine; }); } +void PlatformView::CreateEngine() { + engine_.reset(new Engine(this)); +} + void PlatformView::DispatchPlatformMessage( ftl::RefPtr message) { blink::Threads::UI()->PostTask( @@ -124,6 +127,12 @@ ftl::WeakPtr PlatformView::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } +VsyncWaiter* PlatformView::GetVsyncWaiter() { + if (!vsync_waiter_) + vsync_waiter_ = std::make_unique(); + return vsync_waiter_.get(); +} + void PlatformView::UpdateSemantics(std::vector update) {} void PlatformView::HandlePlatformMessage( diff --git a/engine/src/flutter/shell/common/platform_view.h b/engine/src/flutter/shell/common/platform_view.h index 97ff4da4b35..2c37062fa5a 100644 --- a/engine/src/flutter/shell/common/platform_view.h +++ b/engine/src/flutter/shell/common/platform_view.h @@ -11,6 +11,7 @@ #include "flutter/shell/common/engine.h" #include "flutter/shell/common/shell.h" #include "flutter/shell/common/surface.h" +#include "flutter/shell/common/vsync_waiter.h" #include "lib/ftl/macros.h" #include "lib/ftl/memory/weak_ptr.h" #include "lib/ftl/synchronization/waitable_event.h" @@ -51,6 +52,9 @@ class PlatformView { ftl::WeakPtr GetWeakPtr(); + // The VsyncWaiter will live at least as long as the PlatformView. + virtual VsyncWaiter* GetVsyncWaiter(); + virtual bool ResourceContextMakeCurrent() = 0; virtual void UpdateSemantics(std::vector update); @@ -67,12 +71,15 @@ class PlatformView { protected: explicit PlatformView(std::unique_ptr rasterizer); + void CreateEngine(); + void SetupResourceContextOnIOThreadPerform( ftl::AutoResetWaitableEvent* event); SurfaceConfig surface_config_; std::unique_ptr rasterizer_; std::unique_ptr engine_; + std::unique_ptr vsync_waiter_; SkISize size_; private: diff --git a/engine/src/flutter/shell/common/vsync_waiter.cc b/engine/src/flutter/shell/common/vsync_waiter.cc new file mode 100644 index 00000000000..5acc235b1f6 --- /dev/null +++ b/engine/src/flutter/shell/common/vsync_waiter.cc @@ -0,0 +1,11 @@ +// Copyright 2015 The Chromium 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/vsync_waiter.h" + +namespace shell { + +VsyncWaiter::~VsyncWaiter() = default; + +} // namespace shell diff --git a/engine/src/flutter/shell/common/vsync_waiter.h b/engine/src/flutter/shell/common/vsync_waiter.h new file mode 100644 index 00000000000..c061e0e7d42 --- /dev/null +++ b/engine/src/flutter/shell/common/vsync_waiter.h @@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium 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_SHELL_COMMON_VSYNC_WAITER_H_ +#define FLUTTER_SHELL_COMMON_VSYNC_WAITER_H_ + +#include + +#include "lib/ftl/time/time_point.h" + +namespace shell { + +class VsyncWaiter { + public: + using Callback = std::function; + + virtual void AsyncWaitForVsync(Callback callback) = 0; + + virtual ~VsyncWaiter(); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_COMMON_VSYNC_WAITER_H_ diff --git a/engine/src/flutter/shell/common/vsync_waiter_fallback.cc b/engine/src/flutter/shell/common/vsync_waiter_fallback.cc new file mode 100644 index 00000000000..e6c671ee346 --- /dev/null +++ b/engine/src/flutter/shell/common/vsync_waiter_fallback.cc @@ -0,0 +1,51 @@ +// Copyright 2016 The Chromium 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/vsync_waiter_fallback.h" + +#include "lib/ftl/logging.h" +#include "flutter/common/threads.h" + +namespace shell { +namespace { + +ftl::TimePoint SnapToNextTick(ftl::TimePoint value, + ftl::TimePoint tick_phase, + ftl::TimeDelta tick_interval) { + ftl::TimeDelta offset = (tick_phase - value) % tick_interval; + if (offset != ftl::TimeDelta::Zero()) + offset = offset + tick_interval; + return value + offset; +} + +} // namespace + +VsyncWaiterFallback::VsyncWaiterFallback() + : phase_(ftl::TimePoint::Now()), weak_factory_(this) {} + +VsyncWaiterFallback::~VsyncWaiterFallback() = default; + +void VsyncWaiterFallback::AsyncWaitForVsync(Callback callback) { + FTL_LOG(INFO) << "VsyncWaiterFallback::AsyncWaitForVsync"; + FTL_DCHECK(!callback_); + callback_ = std::move(callback); + + constexpr ftl::TimeDelta interval = ftl::TimeDelta::FromSecondsF(1.0 / 60.0); + + ftl::TimePoint now = ftl::TimePoint::Now(); + ftl::TimePoint next = SnapToNextTick(now, phase_, interval); + + blink::Threads::UI()->PostDelayedTask( + [self = weak_factory_.GetWeakPtr()] { + if (!self) + return; + ftl::TimePoint frame_time = ftl::TimePoint::Now(); + Callback callback = std::move(self->callback_); + self->callback_ = Callback(); + callback(frame_time); + }, + next - now); +} + +} // namespace shell diff --git a/engine/src/flutter/shell/common/vsync_waiter_fallback.h b/engine/src/flutter/shell/common/vsync_waiter_fallback.h new file mode 100644 index 00000000000..d9978c2ee39 --- /dev/null +++ b/engine/src/flutter/shell/common/vsync_waiter_fallback.h @@ -0,0 +1,33 @@ +// Copyright 2015 The Chromium 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_SHELL_COMMON_VSYNC_WAITER_FALLBACK_H_ +#define FLUTTER_SHELL_COMMON_VSYNC_WAITER_FALLBACK_H_ + +#include "flutter/shell/common/vsync_waiter.h" +#include "lib/ftl/macros.h" +#include "lib/ftl/memory/weak_ptr.h" +#include "lib/ftl/time/time_point.h" + +namespace shell { + +class VsyncWaiterFallback : public VsyncWaiter { + public: + VsyncWaiterFallback(); + ~VsyncWaiterFallback() override; + + void AsyncWaitForVsync(Callback callback) override; + + private: + ftl::TimePoint phase_; + Callback callback_; + + ftl::WeakPtrFactory weak_factory_; + + FTL_DISALLOW_COPY_AND_ASSIGN(VsyncWaiterFallback); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_COMMON_VSYNC_WAITER_FALLBACK_H_ diff --git a/engine/src/flutter/shell/platform/android/BUILD.gn b/engine/src/flutter/shell/platform/android/BUILD.gn index be515f57556..cf35858707d 100644 --- a/engine/src/flutter/shell/platform/android/BUILD.gn +++ b/engine/src/flutter/shell/platform/android/BUILD.gn @@ -11,6 +11,7 @@ generate_jni("jni_headers") { sources = [ "io/flutter/view/FlutterMain.java", "io/flutter/view/FlutterView.java", + "io/flutter/view/VsyncWaiter.java", ] jni_package = "shell" } @@ -32,6 +33,8 @@ shared_library("sky_shell") { "library_loader.cc", "platform_view_android.cc", "platform_view_android.h", + "vsync_waiter_android.cc", + "vsync_waiter_android.h", ] deps = [ @@ -78,6 +81,7 @@ android_library("java") { "io/flutter/view/ServiceFactory.java", "io/flutter/view/ServiceProviderImpl.java", "io/flutter/view/ServiceRegistry.java", + "io/flutter/view/VsyncWaiter.java", "org/domokit/sky/shell/SkyActivity.java", "org/domokit/sky/shell/SkyApplication.java", ] @@ -86,7 +90,6 @@ android_library("java") { "//base:base_java", "//flutter/services/engine:interfaces_java", "//flutter/services/platform:interfaces_java", - "//flutter/services/vsync:vsync_lib", "//mojo/android:system_java", "//mojo/public/interfaces/application:application_java", "//mojo/public/java:bindings", diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java b/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java index 9ee102e00a1..068f32b8e07 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java @@ -34,8 +34,6 @@ import org.chromium.mojo.bindings.Interface.Binding; import org.chromium.mojo.system.Core; import org.chromium.mojo.system.impl.CoreImpl; import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojom.vsync.VSyncProvider; -import org.domokit.vsync.VSyncProviderImpl; /** * A class to intialize the Flutter engine. @@ -135,8 +133,6 @@ public class FlutterMain { // of the JNI call is negligible). long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis; nativeRecordStartTimestamp(initTimeMillis); - - onServiceRegistryAvailable(applicationContext, ServiceRegistry.SHARED); } /** @@ -179,15 +175,6 @@ public class FlutterMain { private static native void nativeInit(Context context, String[] args); private static native void nativeRecordStartTimestamp(long initTimeMillis); - private static void onServiceRegistryAvailable(final Context applicationContext, ServiceRegistry registry) { - registry.register(VSyncProvider.MANAGER.getName(), new ServiceFactory() { - @Override - public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) { - return VSyncProvider.MANAGER.bind(new VSyncProviderImpl(pipe), pipe); - } - }); - } - /** * Initialize our Flutter config values by obtaining them from the * manifest XML file, falling back to default values. diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterView.java b/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterView.java index 30d12306754..c0c70ac1d0b 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterView.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterView.java @@ -44,7 +44,6 @@ import org.chromium.mojo.system.Pair; import org.chromium.mojo.system.impl.CoreImpl; import org.chromium.mojom.mojo.ServiceProvider; import org.chromium.mojom.sky.AppLifecycleState; -import org.chromium.mojom.sky.ServicesData; import org.chromium.mojom.sky.SkyEngine; import org.chromium.mojom.sky.ViewportMetrics; @@ -75,8 +74,6 @@ public class FlutterView extends SurfaceView private TextInputPlugin mTextInputPlugin; private SkyEngine.Proxy mSkyEngine; - private ServiceProviderImpl mPlatformServiceProvider; - private Binding mPlatformServiceProviderBinding; private HashMap mOnMessageListeners; private HashMap mAsyncOnMessageListeners; private final SurfaceHolder.Callback mSurfaceCallback; @@ -131,8 +128,6 @@ public class FlutterView extends SurfaceView Core core = CoreImpl.getInstance(); - mPlatformServiceProvider = new ServiceProviderImpl(core, this, ServiceRegistry.SHARED); - mAccessibilityManager = (AccessibilityManager)getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); mOnMessageListeners = new HashMap(); @@ -236,11 +231,6 @@ public class FlutterView extends SurfaceView getContext().unregisterReceiver(discoveryReceiver); } - if (mPlatformServiceProviderBinding != null) { - mPlatformServiceProviderBinding.unbind().close(); - mPlatformServiceProvider.unbindServices(); - } - getHolder().removeCallback(mSurfaceCallback); nativeDetach(mNativePlatformView); mNativePlatformView = 0; @@ -446,22 +436,6 @@ public class FlutterView extends SurfaceView } private void preRun() { - if (mPlatformServiceProviderBinding != null) { - mPlatformServiceProviderBinding.unbind().close(); - mPlatformServiceProvider.unbindServices(); - } - - Core core = CoreImpl.getInstance(); - - Pair> platformServiceProvider = - ServiceProvider.MANAGER.getInterfaceRequest(core); - mPlatformServiceProviderBinding = ServiceProvider.MANAGER.bind( - mPlatformServiceProvider, platformServiceProvider.second); - - ServicesData services = new ServicesData(); - services.incomingServices = platformServiceProvider.first; - mSkyEngine.setServices(services); - resetAccessibilityTree(); } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/ServiceRegistry.java b/engine/src/flutter/shell/platform/android/io/flutter/view/ServiceRegistry.java index 0973a6087af..1c3a95d9275 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/ServiceRegistry.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/ServiceRegistry.java @@ -18,8 +18,6 @@ class ServiceRegistry { static final ServiceRegistry SHARED = new ServiceRegistry(); - // In addition to the shared registry, there is a per-view registry - // maintained by the PlatformServiceProvider. ServiceRegistry() { mRegistrations = new TreeMap(); } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java b/engine/src/flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java new file mode 100644 index 00000000000..6d319f149e3 --- /dev/null +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java @@ -0,0 +1,25 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.view; + +import android.view.Choreographer; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; + +@JNINamespace("shell") +public class VsyncWaiter { + @CalledByNative + public static void asyncWaitForVsync(final long cookie) { + Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + nativeOnVsync(frameTimeNanos, cookie); + } + }); + } + + private static native void nativeOnVsync(long frameTimeNanos, long cookie); +} diff --git a/engine/src/flutter/shell/platform/android/library_loader.cc b/engine/src/flutter/shell/platform/android/library_loader.cc index a50d132e054..887c251c6fb 100644 --- a/engine/src/flutter/shell/platform/android/library_loader.cc +++ b/engine/src/flutter/shell/platform/android/library_loader.cc @@ -14,6 +14,7 @@ #include "mojo/android/system/core_impl.h" #include "flutter/shell/platform/android/flutter_main.h" #include "flutter/shell/platform/android/platform_view_android.h" +#include "flutter/shell/platform/android/vsync_waiter_android.h" namespace { @@ -21,6 +22,7 @@ base::android::RegistrationMethod kSkyRegisteredMethods[] = { {"CoreImpl", mojo::android::RegisterCoreImpl}, {"BaseRunLoop", mojo::android::RegisterBaseRunLoop}, {"FlutterView", shell::PlatformViewAndroid::Register}, + {"VsyncWaiter", shell::VsyncWaiterAndroid::Register}, {"FlutterMain", shell::RegisterFlutterMain}, }; diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.cc b/engine/src/flutter/shell/platform/android/platform_view_android.cc index 6d7ebf1104b..83e1e32c103 100644 --- a/engine/src/flutter/shell/platform/android/platform_view_android.cc +++ b/engine/src/flutter/shell/platform/android/platform_view_android.cc @@ -25,6 +25,7 @@ #include "flutter/shell/common/engine.h" #include "flutter/shell/common/shell.h" #include "flutter/shell/gpu/gpu_rasterizer.h" +#include "flutter/shell/platform/android/vsync_waiter_android.h" #include "jni/FlutterView_jni.h" #include "lib/ftl/functional/make_copyable.h" #include "third_party/skia/include/core/SkSurface.h" @@ -62,7 +63,9 @@ class PlatformMessageResponseAndroid : public blink::PlatformMessageResponse { } // namespace PlatformViewAndroid::PlatformViewAndroid() - : PlatformView(std::make_unique()) {} + : PlatformView(std::make_unique()) { + CreateEngine(); +} PlatformViewAndroid::~PlatformViewAndroid() = default; @@ -259,6 +262,12 @@ void PlatformViewAndroid::ReleaseSurface() { } } +VsyncWaiter* PlatformViewAndroid::GetVsyncWaiter() { + if (!vsync_waiter_) + vsync_waiter_ = std::make_unique(); + return vsync_waiter_.get(); +} + bool PlatformViewAndroid::ResourceContextMakeCurrent() { return surface_gl_ ? surface_gl_->GLOffscreenContextMakeCurrent() : false; } diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.h b/engine/src/flutter/shell/platform/android/platform_view_android.h index b4f7fc3596d..8ab430b0c4a 100644 --- a/engine/src/flutter/shell/platform/android/platform_view_android.h +++ b/engine/src/flutter/shell/platform/android/platform_view_android.h @@ -60,6 +60,8 @@ class PlatformViewAndroid : public PlatformView { base::android::ScopedJavaLocalRef GetBitmap(JNIEnv* env, jobject obj); + VsyncWaiter* GetVsyncWaiter() override; + bool ResourceContextMakeCurrent() override; void UpdateSemantics(std::vector update) override; diff --git a/engine/src/flutter/shell/platform/android/vsync_waiter_android.cc b/engine/src/flutter/shell/platform/android/vsync_waiter_android.cc new file mode 100644 index 00000000000..a927121cf2a --- /dev/null +++ b/engine/src/flutter/shell/platform/android/vsync_waiter_android.cc @@ -0,0 +1,58 @@ +// Copyright 2016 The Chromium 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/platform/android/vsync_waiter_android.h" + +#include + +#include "jni/VsyncWaiter_jni.h" +#include "lib/ftl/logging.h" +#include "flutter/common/threads.h" + +namespace shell { + +VsyncWaiterAndroid::VsyncWaiterAndroid() : weak_factory_(this) {} + +VsyncWaiterAndroid::~VsyncWaiterAndroid() = default; + +void VsyncWaiterAndroid::AsyncWaitForVsync(Callback callback) { + FTL_DCHECK(!callback_); + callback_ = std::move(callback); + ftl::WeakPtr* weak = + new ftl::WeakPtr(); + *weak = weak_factory_.GetWeakPtr(); + + blink::Threads::Platform()->PostTask([weak] { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_VsyncWaiter_asyncWaitForVsync(env, reinterpret_cast(weak)); + }); +} + +void VsyncWaiterAndroid::OnVsync(long frameTimeNanos) { + Callback callback = std::move(callback_); + callback_ = Callback(); + + blink::Threads::UI()->PostTask([callback, frameTimeNanos] { + callback(ftl::TimePoint::FromEpochDelta( + ftl::TimeDelta::FromNanoseconds(frameTimeNanos))); + }); +} + +static void OnVsync(JNIEnv* env, + jclass jcaller, + jlong frameTimeNanos, + jlong cookie) { + ftl::WeakPtr* weak = + reinterpret_cast*>(cookie); + VsyncWaiterAndroid* waiter = weak->get(); + delete weak; + if (waiter) + waiter->OnVsync(frameTimeNanos); +} + +bool VsyncWaiterAndroid::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace shell diff --git a/engine/src/flutter/shell/platform/android/vsync_waiter_android.h b/engine/src/flutter/shell/platform/android/vsync_waiter_android.h new file mode 100644 index 00000000000..0fb884787e5 --- /dev/null +++ b/engine/src/flutter/shell/platform/android/vsync_waiter_android.h @@ -0,0 +1,37 @@ +// Copyright 2016 The Chromium 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 SHELL_PLATFORM_ANDROID_VSYNC_WAITER_ANDROID_H_ +#define SHELL_PLATFORM_ANDROID_VSYNC_WAITER_ANDROID_H_ + +#include "base/android/jni_android.h" +#include "flutter/shell/common/vsync_waiter.h" +#include "lib/ftl/macros.h" +#include "lib/ftl/memory/weak_ptr.h" + +namespace shell { + +class VsyncWaiterAndroid : public VsyncWaiter { + public: + VsyncWaiterAndroid(); + ~VsyncWaiterAndroid() override; + + static bool Register(JNIEnv* env); + + void AsyncWaitForVsync(Callback callback) override; + + void OnVsync(long frameTimeNanos); + + private: + Callback callback_; + ftl::WeakPtr self_; + + ftl::WeakPtrFactory weak_factory_; + + FTL_DISALLOW_COPY_AND_ASSIGN(VsyncWaiterAndroid); +}; + +} // namespace shell + +#endif // SHELL_PLATFORM_ANDROID_ASYNC_WAITER_ANDROID_H_ diff --git a/engine/src/flutter/shell/platform/darwin/common/BUILD.gn b/engine/src/flutter/shell/platform/darwin/common/BUILD.gn index 71c969df101..f7622fcccb0 100644 --- a/engine/src/flutter/shell/platform/darwin/common/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/common/BUILD.gn @@ -9,8 +9,6 @@ source_set("common") { sources = [ "platform_mac.h", "platform_mac.mm", - "platform_service_provider.cc", - "platform_service_provider.h", "string_conversions.mm", "string_conversions.h", ] @@ -23,7 +21,6 @@ source_set("common") { "//flutter/runtime", "//flutter/services/engine:interfaces", "//flutter/services/platform", - "//flutter/services/vsync", "//flutter/shell/common", "//flutter/shell/gpu", "//flutter/shell/testing", diff --git a/engine/src/flutter/shell/platform/darwin/common/platform_service_provider.cc b/engine/src/flutter/shell/platform/darwin/common/platform_service_provider.cc deleted file mode 100644 index 45c58e36e74..00000000000 --- a/engine/src/flutter/shell/platform/darwin/common/platform_service_provider.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 The Chromium 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/platform/darwin/common/platform_service_provider.h" - -#if TARGET_OS_IPHONE -#include "flutter/services/vsync/ios/vsync_provider_ios_impl.h" -#else -#include "flutter/services/vsync/mac/vsync_provider_mac_impl.h" -#endif // TARGET_OS_IPHONE - -namespace shell { - -PlatformServiceProvider::PlatformServiceProvider( - mojo::InterfaceRequest request) - : binding_(this, request.Pass()) {} - -PlatformServiceProvider::~PlatformServiceProvider() {} - -void PlatformServiceProvider::ConnectToService( - const mojo::String& service_name, - mojo::ScopedMessagePipeHandle client_handle) { -#if TARGET_OS_IPHONE - if (service_name == ::vsync::VSyncProvider::Name_) { - new sky::services::vsync::VsyncProviderIOSImpl( - mojo::InterfaceRequest<::vsync::VSyncProvider>(client_handle.Pass())); - return; - } -#else // TARGET_OS_IPHONE - if (service_name == ::vsync::VSyncProvider::Name_) { - new sky::services::vsync::VsyncProviderMacImpl( - mojo::InterfaceRequest<::vsync::VSyncProvider>(client_handle.Pass())); - return; - } -#endif // TARGET_OS_IPHONE -} - -} // namespace shell diff --git a/engine/src/flutter/shell/platform/darwin/common/platform_service_provider.h b/engine/src/flutter/shell/platform/darwin/common/platform_service_provider.h deleted file mode 100644 index 09a06eecf8c..00000000000 --- a/engine/src/flutter/shell/platform/darwin/common/platform_service_provider.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 The Chromium 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 SHELL_PLATFORM_MAC_PLATFORM_SERVICE_PROVIDER_H_ -#define SHELL_PLATFORM_MAC_PLATFORM_SERVICE_PROVIDER_H_ - -#include "base/callback.h" -#include "lib/ftl/macros.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" - -namespace shell { - -class PlatformServiceProvider : public mojo::ServiceProvider { - public: - PlatformServiceProvider(mojo::InterfaceRequest request); - - ~PlatformServiceProvider() override; - - void ConnectToService(const mojo::String& service_name, - mojo::ScopedMessagePipeHandle client_handle) override; - - private: - mojo::StrongBinding binding_; - - FTL_DISALLOW_COPY_AND_ASSIGN(PlatformServiceProvider); -}; - -} // namespace shell - -#endif // SHELL_PLATFORM_MAC_PLATFORM_SERVICE_PROVIDER_H_ diff --git a/engine/src/flutter/shell/platform/darwin/desktop/BUILD.gn b/engine/src/flutter/shell/platform/darwin/desktop/BUILD.gn index 8fb26edb282..194e3fa84db 100644 --- a/engine/src/flutter/shell/platform/darwin/desktop/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/desktop/BUILD.gn @@ -19,6 +19,8 @@ source_set("mac_desktop_platform") { "sky_application.mm", "sky_window.h", "sky_window.mm", + "vsync_waiter_mac.cc", + "vsync_waiter_mac.h", ] deps = [ diff --git a/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.h b/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.h index d2bda9180ed..6b308cf0423 100644 --- a/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.h +++ b/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.h @@ -33,6 +33,8 @@ class PlatformViewMac : public PlatformView, public GPUSurfaceGLDelegate { intptr_t GLContextFBO() const override; + VsyncWaiter* GetVsyncWaiter() override; + bool ResourceContextMakeCurrent() override; void RunFromSource(const std::string& main, diff --git a/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm b/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm index e720a4bdb28..e8666e77327 100644 --- a/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm +++ b/engine/src/flutter/shell/platform/darwin/desktop/platform_view_mac.mm @@ -12,7 +12,7 @@ #include "flutter/shell/common/switches.h" #include "flutter/shell/gpu/gpu_rasterizer.h" #include "flutter/shell/platform/darwin/common/platform_mac.h" -#include "flutter/shell/platform/darwin/common/platform_service_provider.h" +#include "flutter/shell/platform/darwin/desktop/vsync_waiter_mac.h" #include "lib/ftl/synchronization/waitable_event.h" namespace shell { @@ -23,6 +23,8 @@ PlatformViewMac::PlatformViewMac(NSOpenGLView* gl_view) resource_loading_context_([[NSOpenGLContext alloc] initWithFormat:gl_view.pixelFormat shareContext:gl_view.openGLContext]) { + CreateEngine(); + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); if (paths.count > 0) { @@ -35,13 +37,6 @@ PlatformViewMac::~PlatformViewMac() = default; void PlatformViewMac::ConnectToEngineAndSetupServices() { ConnectToEngine(mojo::GetProxy(&sky_engine_)); - - mojo::ServiceProviderPtr service_provider; - new PlatformServiceProvider(mojo::GetProxy(&service_provider)); - - sky::ServicesDataPtr services = sky::ServicesData::New(); - services->incoming_services = service_provider.Pass(); - sky_engine_->SetServices(services.Pass()); } void PlatformViewMac::SetupAndLoadDart() { @@ -118,6 +113,12 @@ bool PlatformViewMac::GLContextPresent() { return true; } +VsyncWaiter* PlatformViewMac::GetVsyncWaiter() { + if (!vsync_waiter_) + vsync_waiter_ = std::make_unique(); + return vsync_waiter_.get(); +} + bool PlatformViewMac::ResourceContextMakeCurrent() { NSOpenGLContext* context = resource_loading_context_.get(); diff --git a/engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.cc b/engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.cc new file mode 100644 index 00000000000..2a34d099584 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.cc @@ -0,0 +1,58 @@ +// Copyright 2015 The Chromium 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/platform/darwin/desktop/vsync_waiter_mac.h" + +#include + +#include "flutter/common/threads.h" +#include "lib/ftl/logging.h" + +namespace shell { + +#define link_ (reinterpret_cast(opaque_)) + +VsyncWaiterMac::VsyncWaiterMac() : opaque_(nullptr) { + // Create the link. + CVDisplayLinkRef link = nullptr; + CVDisplayLinkCreateWithActiveCGDisplays(&link); + opaque_ = link; + + // Set the output callback. + CVDisplayLinkSetOutputCallback( + link_, + [](CVDisplayLinkRef link, const CVTimeStamp* now, + const CVTimeStamp* output, CVOptionFlags flags_in, + CVOptionFlags* flags_out, void* context) -> CVReturn { + OnDisplayLink(context); + return kCVReturnSuccess; + }, + this); +} + +VsyncWaiterMac::~VsyncWaiterMac() { + CVDisplayLinkRelease(link_); +} + +void VsyncWaiterMac::OnDisplayLink(void* context) { + reinterpret_cast(context)->OnDisplayLink(); +} + +void VsyncWaiterMac::OnDisplayLink() { + ftl::TimePoint frame_time = ftl::TimePoint::Now(); + CVDisplayLinkStop(link_); + auto callback = std::move(callback_); + callback_ = Callback(); + + blink::Threads::UI()->PostTask( + [callback, frame_time] { callback(frame_time); }); +} + +void VsyncWaiterMac::AsyncWaitForVsync(Callback callback) { + FTL_DCHECK(!callback_); + callback_ = std::move(callback); + CVDisplayLinkStart(link_); +} + +} // namespace shell diff --git a/engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.h b/engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.h new file mode 100644 index 00000000000..1e26ea9c5a7 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/desktop/vsync_waiter_mac.h @@ -0,0 +1,33 @@ +// Copyright 2016 The Chromium 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_SHELL_PLATFORM_DARWIN_DESKTOP_VSYNC_WAITER_MAC_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_DESKTOP_VSYNC_WAITER_MAC_H_ + +#include "lib/ftl/macros.h" +#include "flutter/shell/common/vsync_waiter.h" + +namespace shell { + +class VsyncWaiterMac : public VsyncWaiter { + public: + VsyncWaiterMac(); + + ~VsyncWaiterMac() override; + + void AsyncWaitForVsync(Callback callback) override; + + private: + void* opaque_; + Callback callback_; + + static void OnDisplayLink(void* context); + void OnDisplayLink(); + + FTL_DISALLOW_COPY_AND_ASSIGN(VsyncWaiterMac); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_DESKTOP_VSYNC_WAITER_MAC_H_ diff --git a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn index 80d8db55278..3f461c417e7 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/ios/BUILD.gn @@ -43,6 +43,8 @@ shared_library("flutter_framework_dylib") { "framework/Source/FlutterViewController.mm", "framework/Source/platform_message_router.h", "framework/Source/platform_message_router.mm", + "framework/Source/vsync_waiter_ios.h", + "framework/Source/vsync_waiter_ios.mm", "platform_view_ios.h", "platform_view_ios.mm", ] @@ -54,7 +56,6 @@ shared_library("flutter_framework_dylib") { "//flutter/lib/ui", "//flutter/services/engine:interfaces", "//flutter/services/platform", - "//flutter/services/vsync", "//flutter/shell/common", "//flutter/shell/gpu", "//flutter/shell/platform/darwin/common", diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h new file mode 100644 index 00000000000..fa30510b2d6 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h @@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium 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_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_VSYNC_WAITER_IOS_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_VSYNC_WAITER_IOS_H_ + +#include "lib/ftl/macros.h" +#include "flutter/shell/common/vsync_waiter.h" + +#if __OBJC__ +@class VSyncClient; +#else // __OBJC__ +class VSyncClient; +#endif // __OBJC__ + +namespace shell { + +class VsyncWaiterIOS : public VsyncWaiter { + public: + VsyncWaiterIOS(); + ~VsyncWaiterIOS() override; + + void AsyncWaitForVsync(Callback callback) override; + + private: + Callback callback_; + VSyncClient* client_; + + FTL_DISALLOW_COPY_AND_ASSIGN(VsyncWaiterIOS); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_VSYNC_WAITER_IOS_H_ diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm new file mode 100644 index 00000000000..3bd8e0b3110 --- /dev/null +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm @@ -0,0 +1,76 @@ +// Copyright 2015 The Chromium 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/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" + +#include + +#include +#include +#include + +#include "flutter/common/threads.h" +#include "lib/ftl/logging.h" + +@interface VSyncClient : NSObject + +@end + +@implementation VSyncClient { + CADisplayLink* _displayLink; + shell::VsyncWaiter::Callback _pendingCallback; +} + +- (instancetype)init { + self = [super init]; + + if (self) { + _displayLink = [[CADisplayLink + displayLinkWithTarget:self + selector:@selector(onDisplayLink:)] retain]; + _displayLink.paused = YES; + [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] + forMode:NSRunLoopCommonModes]; + } + + return self; +} + +- (void)await:(shell::VsyncWaiter::Callback)callback { + FTL_DCHECK(!_pendingCallback); + _pendingCallback = std::move(callback); + _displayLink.paused = NO; +} + +- (void)onDisplayLink:(CADisplayLink*)link { + ftl::TimePoint frame_time = ftl::TimePoint::Now(); + _displayLink.paused = YES; + auto callback = std::move(_pendingCallback); + _pendingCallback = shell::VsyncWaiter::Callback(); + blink::Threads::UI()->PostTask( + [callback, frame_time] { callback(frame_time); }); +} + +- (void)dealloc { + [_displayLink invalidate]; + [_displayLink release]; + + [super dealloc]; +} + +@end + +namespace shell { + +VsyncWaiterIOS::VsyncWaiterIOS() : client_([[VSyncClient alloc] init]) {} + +VsyncWaiterIOS::~VsyncWaiterIOS() { + [client_ release]; +} + +void VsyncWaiterIOS::AsyncWaitForVsync(Callback callback) { + [client_ await:std::move(callback)]; +} + +} // namespace shell diff --git a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h index 1b289312b68..bea98e8b857 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h +++ b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.h @@ -38,6 +38,8 @@ class PlatformViewIOS : public PlatformView, public GPUSurfaceGLDelegate { return platform_message_router_; } + VsyncWaiter* GetVsyncWaiter() override; + bool ResourceContextMakeCurrent() override; bool GLContextMakeCurrent() override; diff --git a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm index 78062d6bb9f..bfc498b11a9 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/platform_view_ios.mm @@ -14,7 +14,7 @@ #include "base/mac/scoped_nsautorelease_pool.h" #include "base/trace_event/trace_event.h" #include "flutter/shell/gpu/gpu_rasterizer.h" -#include "flutter/shell/platform/darwin/common/platform_service_provider.h" +#include "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" #include "lib/ftl/synchronization/waitable_event.h" #include "mojo/public/cpp/application/connect.h" @@ -276,6 +276,8 @@ class IOSGLContext { PlatformViewIOS::PlatformViewIOS(CAEAGLLayer* layer) : PlatformView(std::make_unique()), context_(std::make_unique(surface_config_, layer)) { + CreateEngine(); + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); shell::Shell::Shared().tracing_controller().set_traces_base_path( @@ -291,8 +293,7 @@ sky::SkyEnginePtr& PlatformViewIOS::engineProxy() { void PlatformViewIOS::ToggleAccessibility(UIView* view, bool enabled) { if (enabled) { if (!accessibility_bridge_) { - accessibility_bridge_.reset( - new shell::AccessibilityBridge(view, this)); + accessibility_bridge_.reset(new shell::AccessibilityBridge(view, this)); } } else { accessibility_bridge_ = nullptr; @@ -302,13 +303,6 @@ void PlatformViewIOS::ToggleAccessibility(UIView* view, bool enabled) { void PlatformViewIOS::ConnectToEngineAndSetupServices() { ConnectToEngine(mojo::GetProxy(&engine_)); - - mojo::ServiceProviderPtr service_provider; - new PlatformServiceProvider(mojo::GetProxy(&service_provider)); - - sky::ServicesDataPtr services = sky::ServicesData::New(); - services->incoming_services = service_provider.Pass(); - engine_->SetServices(services.Pass()); } void PlatformViewIOS::SetupAndLoadFromSource( @@ -319,6 +313,12 @@ void PlatformViewIOS::SetupAndLoadFromSource( engine_->RunFromFile(main, packages, assets_directory); } +VsyncWaiter* PlatformViewIOS::GetVsyncWaiter() { + if (!vsync_waiter_) + vsync_waiter_ = std::make_unique(); + return vsync_waiter_.get(); +} + bool PlatformViewIOS::ResourceContextMakeCurrent() { return context_ != nullptr ? context_->ResourceMakeCurrent() : false; } diff --git a/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc b/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc index 0618034ed69..b755163662a 100644 --- a/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc +++ b/engine/src/flutter/shell/platform/linux/platform_view_glfw.cc @@ -19,6 +19,8 @@ PlatformViewGLFW::PlatformViewGLFW() valid_(false), glfw_window_(nullptr), buttons_(0) { + CreateEngine(); + if (!glfwInit()) { return; } @@ -60,13 +62,6 @@ PlatformViewGLFW::~PlatformViewGLFW() { void PlatformViewGLFW::ConnectToEngineAndSetupServices() { ConnectToEngine(mojo::GetProxy(&engine_)); - - mojo::ServiceProviderPtr platform_service_provider; - new GLFWServiceProvider(mojo::GetProxy(&platform_service_provider)); - - sky::ServicesDataPtr services = sky::ServicesData::New(); - services->incoming_services = platform_service_provider.Pass(); - engine_->SetServices(services.Pass()); } sky::SkyEnginePtr& PlatformViewGLFW::EngineProxy() { diff --git a/engine/src/flutter/shell/testing/platform_view_test.cc b/engine/src/flutter/shell/testing/platform_view_test.cc index 04340a36fa4..69909de57af 100644 --- a/engine/src/flutter/shell/testing/platform_view_test.cc +++ b/engine/src/flutter/shell/testing/platform_view_test.cc @@ -10,7 +10,9 @@ namespace shell { PlatformViewTest::PlatformViewTest() - : PlatformView(std::unique_ptr(new NullRasterizer())) {} + : PlatformView(std::unique_ptr(new NullRasterizer())) { + CreateEngine(); +} PlatformViewTest::~PlatformViewTest() = default;