mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Drive frames from the vsync provider on Android
Instead of using back pressure from swap buffers to drive the engine, this patch using the vsync signal from the Android framework. We still respect back pressure from swap buffers if we get too far ahead.
This commit is contained in:
parent
df5c6f1db5
commit
f81d96e1dd
@ -28,5 +28,6 @@ dart_pkg("sky_services") {
|
||||
"//sky/services/activity:interfaces",
|
||||
"//sky/services/media:interfaces",
|
||||
"//sky/services/testing:interfaces",
|
||||
"//sky/services/vsync:interfaces",
|
||||
]
|
||||
}
|
||||
|
||||
39
sky/services/vsync/BUILD.gn
Normal file
39
sky/services/vsync/BUILD.gn
Normal file
@ -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",
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
9
sky/services/vsync/vsync.mojom
Normal file
9
sky/services/vsync/vsync.mojom
Normal file
@ -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);
|
||||
};
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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<SkPicture> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user