diff --git a/sky/packages/sky_services/BUILD.gn b/sky/packages/sky_services/BUILD.gn index 3fcd4fd086032bd65b5a99ba0f063dcb0a151056..049dc468c41b3e2bcdcc768bbfdde8045e9e2a86 100644 --- a/sky/packages/sky_services/BUILD.gn +++ b/sky/packages/sky_services/BUILD.gn @@ -28,5 +28,6 @@ dart_pkg("sky_services") { "//sky/services/activity:interfaces", "//sky/services/media:interfaces", "//sky/services/testing:interfaces", + "//sky/services/vsync:interfaces", ] } diff --git a/sky/services/vsync/BUILD.gn b/sky/services/vsync/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8b9e4200181a515d97a607562d77bcfb759db82e --- /dev/null +++ b/sky/services/vsync/BUILD.gn @@ -0,0 +1,39 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") + +group("vsync") { + testonly = true + + deps = [ + ":interfaces", + ] + + if (is_android) { + deps += [ ":vsync_lib" ] + } +} + +mojom("interfaces") { + sources = [ + "vsync.mojom", + ] +} + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") + + android_library("vsync_lib") { + java_files = [ "src/org/domokit/vsync/VsyncProviderImpl.java" ] + + deps = [ + "//base:base_java", + "//mojo/public/java:bindings", + "//mojo/public/java:system", + ":interfaces_java", + ] + } +} diff --git a/sky/services/vsync/src/org/domokit/vsync/VsyncProviderImpl.java b/sky/services/vsync/src/org/domokit/vsync/VsyncProviderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fa0d6d28bfd0fac32b3b5d04e5ddea5587a8f1bf --- /dev/null +++ b/sky/services/vsync/src/org/domokit/vsync/VsyncProviderImpl.java @@ -0,0 +1,36 @@ +// 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. + +package org.domokit.vsync; + +import android.view.Choreographer; + +import org.chromium.mojo.system.MojoException; +import org.chromium.mojom.vsync.VsyncProvider; + +/** + * Android implementation of VsyncProvider. + */ +public class VsyncProviderImpl implements VsyncProvider { + private static final String TAG = "VsyncProviderImpl"; + + public VsyncProviderImpl() { + } + + @Override + public void close() {} + + @Override + public void onConnectionError(MojoException e) {} + + @Override + public void awaitVsync(final AwaitVsyncResponse callback) { + Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + callback.call(frameTimeNanos); + } + }); + } +} diff --git a/sky/services/vsync/vsync.mojom b/sky/services/vsync/vsync.mojom new file mode 100644 index 0000000000000000000000000000000000000000..d4445bac749013878e21bf6b215d3f0563904f84 --- /dev/null +++ b/sky/services/vsync/vsync.mojom @@ -0,0 +1,9 @@ +// 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. + +module vsync; + +interface VsyncProvider { + AwaitVsync() => (int64 time_stamp); +}; diff --git a/sky/shell/BUILD.gn b/sky/shell/BUILD.gn index 3c17d7e8c6024990b139a77631b887f806f640e7..bc152d1eeda3132c2cc225c99e1f0c7bb407726d 100644 --- a/sky/shell/BUILD.gn +++ b/sky/shell/BUILD.gn @@ -20,6 +20,7 @@ common_deps = [ "//sky/engine/tonic", "//sky/engine/wtf", "//sky/services/engine:interfaces", + "//sky/services/vsync:interfaces", "//sky/shell/dart", "//ui/gfx/geometry", "//ui/gl", @@ -134,6 +135,8 @@ if (is_android) { "//sky/services/media:interfaces_java", "//sky/services/media:media_lib", "//sky/services/oknet", + "//sky/services/vsync:interfaces_java", + "//sky/services/vsync:vsync_lib", ] } diff --git a/sky/shell/android/org/domokit/sky/shell/SkyApplication.java b/sky/shell/android/org/domokit/sky/shell/SkyApplication.java index a871d47ad55d737ee5efe79930c684495fa928ae..f89fae83102982b357f02002f5f1a91abd48ab50 100644 --- a/sky/shell/android/org/domokit/sky/shell/SkyApplication.java +++ b/sky/shell/android/org/domokit/sky/shell/SkyApplication.java @@ -21,9 +21,11 @@ import org.chromium.mojom.keyboard.KeyboardService; import org.chromium.mojom.media.MediaService; import org.chromium.mojom.mojo.NetworkService; import org.chromium.mojom.sensors.SensorService; +import org.chromium.mojom.vsync.VsyncProvider; import org.domokit.activity.ActivityImpl; import org.domokit.media.MediaServiceImpl; import org.domokit.oknet.NetworkServiceImpl; +import org.domokit.vsync.VsyncProviderImpl; /** * Sky implementation of {@link android.app.Application}, managing application-level global @@ -97,6 +99,13 @@ public class SkyApplication extends BaseChromiumApplication { SensorService.MANAGER.bind(new SensorServiceImpl(context), pipe); } }); + + registry.register(VsyncProvider.MANAGER.getName(), new ServiceFactory() { + @Override + public void connectToService(Context context, Core core, MessagePipeHandle pipe) { + VsyncProvider.MANAGER.bind(new VsyncProviderImpl(), pipe); + } + }); } private void initJavaUtils() { diff --git a/sky/shell/ui/animator.cc b/sky/shell/ui/animator.cc index 83c02bb1fe10c901cbc6e72f445b382eed844453..39eb5cf3124884a3571e4e395f90f599f4b0328c 100644 --- a/sky/shell/ui/animator.cc +++ b/sky/shell/ui/animator.cc @@ -39,9 +39,14 @@ void Animator::RequestFrame() { return; } - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&Animator::BeginFrame, weak_factory_.GetWeakPtr())); + if (vsync_provider_) { + vsync_provider_->AwaitVsync( + base::Bind(&Animator::BeginFrame, weak_factory_.GetWeakPtr())); + } else { + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&Animator::BeginFrame, weak_factory_.GetWeakPtr(), 0)); + } } void Animator::Stop() { @@ -54,7 +59,7 @@ void Animator::Start() { RequestFrame(); } -void Animator::BeginFrame() { +void Animator::BeginFrame(int64_t time_stamp) { TRACE_EVENT_ASYNC_END0("sky", "Frame request pending", this); DCHECK(engine_requested_frame_); engine_requested_frame_ = false; @@ -62,7 +67,10 @@ void Animator::BeginFrame() { DCHECK(outstanding_requests_ > 0); DCHECK(outstanding_requests_ <= kPipelineDepth) << outstanding_requests_; - engine_->BeginFrame(base::TimeTicks::Now()); + base::TimeTicks frame_time = time_stamp ? + base::TimeTicks::FromInternalValue(time_stamp) : base::TimeTicks::Now(); + + engine_->BeginFrame(frame_time); skia::RefPtr picture = engine_->Paint(); config_.gpu_task_runner->PostTaskAndReply( @@ -79,7 +87,7 @@ void Animator::OnFrameComplete() { if (did_defer_frame_request_) { did_defer_frame_request_ = false; - BeginFrame(); + BeginFrame(0); } } diff --git a/sky/shell/ui/animator.h b/sky/shell/ui/animator.h index 1d8b17d8da4ef67b26b1324c9cb3ba501e108d0e..764b3b01079a2b2bb7cb3fa9dba0217bf1464cbd 100644 --- a/sky/shell/ui/animator.h +++ b/sky/shell/ui/animator.h @@ -6,6 +6,7 @@ #define SKY_SHELL_UI_ANIMATOR_H_ #include "base/memory/weak_ptr.h" +#include "sky/services/vsync/vsync.mojom.h" #include "sky/shell/ui/engine.h" namespace sky { @@ -21,12 +22,17 @@ class Animator { void Start(); void Stop(); + void set_vsync_provider(vsync::VsyncProviderPtr vsync_provider) { + vsync_provider_ = vsync_provider.Pass(); + } + private: - void BeginFrame(); + void BeginFrame(int64_t time_stamp); void OnFrameComplete(); Engine::Config config_; Engine* engine_; + vsync::VsyncProviderPtr vsync_provider_; int outstanding_requests_; bool did_defer_frame_request_; bool engine_requested_frame_; diff --git a/sky/shell/ui/engine.cc b/sky/shell/ui/engine.cc index 800f456aa51d56cc5ce54ea561136da8136758db..840dd9fa0205c7fa7ae4b8000d09f6f48ea14fe9 100644 --- a/sky/shell/ui/engine.cc +++ b/sky/shell/ui/engine.cc @@ -65,6 +65,13 @@ Engine::Engine(const Config& config) mojo::ServiceProviderPtr service_provider = CreateServiceProvider(config.service_provider_context); mojo::ConnectToService(service_provider.get(), &network_service_); + +#if defined(OS_ANDROID) + // TODO(abarth): Implement VsyncProvider on other platforms. + vsync::VsyncProviderPtr vsync_provider; + mojo::ConnectToService(service_provider.get(), &vsync_provider); + animator_->set_vsync_provider(vsync_provider.Pass()); +#endif } Engine::~Engine() {