mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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.
260 lines
7.7 KiB
C++
260 lines
7.7 KiB
C++
// 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 "sky/shell/ui/engine.h"
|
|
|
|
#include "base/bind.h"
|
|
#include "base/files/file_path.h"
|
|
#include "base/threading/worker_pool.h"
|
|
#include "base/trace_event/trace_event.h"
|
|
#include "mojo/common/data_pipe_utils.h"
|
|
#include "mojo/public/cpp/application/connect.h"
|
|
#include "services/asset_bundle/asset_unpacker_job.h"
|
|
#include "sky/engine/public/platform/WebInputEvent.h"
|
|
#include "sky/engine/public/platform/sky_display_metrics.h"
|
|
#include "sky/engine/public/platform/sky_display_metrics.h"
|
|
#include "sky/engine/public/web/Sky.h"
|
|
#include "sky/shell/dart/dart_library_provider_files.h"
|
|
#include "sky/shell/dart/dart_library_provider_network.h"
|
|
#include "sky/shell/service_provider.h"
|
|
#include "sky/shell/ui/animator.h"
|
|
#include "sky/shell/ui/input_event_converter.h"
|
|
#include "sky/shell/ui/internals.h"
|
|
#include "sky/shell/ui/platform_impl.h"
|
|
#include "third_party/skia/include/core/SkCanvas.h"
|
|
#include "third_party/skia/include/core/SkPictureRecorder.h"
|
|
|
|
namespace sky {
|
|
namespace shell {
|
|
|
|
const char kSnapshotKey[] = "snapshot_blob.bin";
|
|
|
|
namespace {
|
|
|
|
void Ignored(bool) {
|
|
}
|
|
|
|
mojo::ScopedDataPipeConsumerHandle Fetch(const base::FilePath& path) {
|
|
mojo::DataPipe pipe;
|
|
auto runner = base::WorkerPool::GetTaskRunner(true);
|
|
mojo::common::CopyFromFile(base::FilePath(path), pipe.producer_handle.Pass(),
|
|
0, runner.get(), base::Bind(&Ignored));
|
|
return pipe.consumer_handle.Pass();
|
|
}
|
|
|
|
PlatformImpl* g_platform_impl = nullptr;
|
|
|
|
} // namespace
|
|
|
|
using mojo::asset_bundle::AssetUnpackerJob;
|
|
|
|
Engine::Config::Config() {
|
|
}
|
|
|
|
Engine::Config::~Config() {
|
|
}
|
|
|
|
Engine::Engine(const Config& config)
|
|
: config_(config),
|
|
animator_(new Animator(config, this)),
|
|
binding_(this),
|
|
activity_running_(false),
|
|
have_surface_(false),
|
|
weak_factory_(this) {
|
|
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() {
|
|
}
|
|
|
|
base::WeakPtr<Engine> Engine::GetWeakPtr() {
|
|
return weak_factory_.GetWeakPtr();
|
|
}
|
|
|
|
void Engine::Init() {
|
|
TRACE_EVENT0("sky", "Engine::Init");
|
|
|
|
DCHECK(!g_platform_impl);
|
|
g_platform_impl = new PlatformImpl();
|
|
blink::initialize(g_platform_impl);
|
|
}
|
|
|
|
void Engine::BeginFrame(base::TimeTicks frame_time) {
|
|
TRACE_EVENT0("sky", "Engine::BeginFrame");
|
|
|
|
if (sky_view_)
|
|
sky_view_->BeginFrame(frame_time);
|
|
}
|
|
|
|
skia::RefPtr<SkPicture> Engine::Paint() {
|
|
TRACE_EVENT0("sky", "Engine::Paint");
|
|
|
|
SkRTreeFactory factory;
|
|
SkPictureRecorder recorder;
|
|
auto canvas = skia::SharePtr(recorder.beginRecording(
|
|
physical_size_.width(), physical_size_.height(), &factory,
|
|
SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag));
|
|
|
|
if (sky_view_) {
|
|
skia::RefPtr<SkPicture> picture = sky_view_->Paint();
|
|
canvas->clear(SK_ColorBLACK);
|
|
canvas->scale(display_metrics_.device_pixel_ratio,
|
|
display_metrics_.device_pixel_ratio);
|
|
if (picture)
|
|
canvas->drawPicture(picture.get());
|
|
}
|
|
|
|
return skia::AdoptRef(recorder.endRecordingAsPicture());
|
|
}
|
|
|
|
void Engine::ConnectToEngine(mojo::InterfaceRequest<SkyEngine> request) {
|
|
binding_.Bind(request.Pass());
|
|
}
|
|
|
|
void Engine::OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) {
|
|
config_.gpu_task_runner->PostTask(
|
|
FROM_HERE, base::Bind(&GPUDelegate::OnAcceleratedWidgetAvailable,
|
|
config_.gpu_delegate, widget));
|
|
have_surface_ = true;
|
|
StartAnimatorIfPossible();
|
|
if (sky_view_)
|
|
ScheduleFrame();
|
|
}
|
|
|
|
void Engine::OnOutputSurfaceDestroyed() {
|
|
have_surface_ = false;
|
|
StopAnimator();
|
|
config_.gpu_task_runner->PostTask(
|
|
FROM_HERE,
|
|
base::Bind(&GPUDelegate::OnOutputSurfaceDestroyed, config_.gpu_delegate));
|
|
}
|
|
|
|
void Engine::OnViewportMetricsChanged(ViewportMetricsPtr metrics) {
|
|
physical_size_.SetSize(metrics->physical_width, metrics->physical_height);
|
|
|
|
display_metrics_.physical_size = physical_size_;
|
|
display_metrics_.device_pixel_ratio = metrics->device_pixel_ratio;
|
|
display_metrics_.padding_top = metrics->padding_top;
|
|
display_metrics_.padding_right = metrics->padding_right;
|
|
display_metrics_.padding_bottom = metrics->padding_bottom;
|
|
display_metrics_.padding_left = metrics->padding_left;
|
|
|
|
if (sky_view_)
|
|
sky_view_->SetDisplayMetrics(display_metrics_);
|
|
}
|
|
|
|
void Engine::OnInputEvent(InputEventPtr event) {
|
|
TRACE_EVENT0("sky", "Engine::OnInputEvent");
|
|
scoped_ptr<blink::WebInputEvent> web_event =
|
|
ConvertEvent(event, display_metrics_.device_pixel_ratio);
|
|
if (!web_event)
|
|
return;
|
|
if (sky_view_)
|
|
sky_view_->HandleInputEvent(*web_event);
|
|
}
|
|
|
|
void Engine::RunFromLibrary(const std::string& name) {
|
|
sky_view_ = blink::SkyView::Create(this);
|
|
sky_view_->RunFromLibrary(blink::WebString::fromUTF8(name),
|
|
dart_library_provider_.get());
|
|
sky_view_->SetDisplayMetrics(display_metrics_);
|
|
}
|
|
|
|
void Engine::RunFromSnapshotStream(
|
|
const std::string& name,
|
|
mojo::ScopedDataPipeConsumerHandle snapshot) {
|
|
sky_view_ = blink::SkyView::Create(this);
|
|
sky_view_->RunFromSnapshot(blink::WebString::fromUTF8(name), snapshot.Pass());
|
|
sky_view_->SetDisplayMetrics(display_metrics_);
|
|
}
|
|
|
|
void Engine::RunFromNetwork(const mojo::String& url) {
|
|
dart_library_provider_.reset(
|
|
new DartLibraryProviderNetwork(network_service_.get()));
|
|
RunFromLibrary(url);
|
|
}
|
|
|
|
void Engine::RunFromFile(const mojo::String& main,
|
|
const mojo::String& package_root) {
|
|
std::string package_root_str = package_root;
|
|
dart_library_provider_.reset(
|
|
new DartLibraryProviderFiles(base::FilePath(package_root_str)));
|
|
RunFromLibrary(main);
|
|
}
|
|
|
|
void Engine::RunFromSnapshot(const mojo::String& path) {
|
|
std::string path_str = path;
|
|
RunFromSnapshotStream(path_str, Fetch(base::FilePath(path_str)));
|
|
}
|
|
|
|
void Engine::RunFromBundle(const mojo::String& path) {
|
|
AssetUnpackerJob* unpacker = new AssetUnpackerJob(
|
|
mojo::GetProxy(&root_bundle_), base::WorkerPool::GetTaskRunner(true));
|
|
std::string path_str = path;
|
|
unpacker->Unpack(Fetch(base::FilePath(path_str)));
|
|
root_bundle_->GetAsStream(kSnapshotKey,
|
|
base::Bind(&Engine::RunFromSnapshotStream,
|
|
weak_factory_.GetWeakPtr(), path_str));
|
|
}
|
|
|
|
void Engine::OnActivityPaused() {
|
|
activity_running_ = false;
|
|
StopAnimator();
|
|
}
|
|
|
|
void Engine::OnActivityResumed() {
|
|
activity_running_ = true;
|
|
StartAnimatorIfPossible();
|
|
}
|
|
|
|
void Engine::DidCreateIsolate(Dart_Isolate isolate) {
|
|
Internals::Create(isolate,
|
|
CreateServiceProvider(config_.service_provider_context),
|
|
root_bundle_.Pass());
|
|
}
|
|
|
|
void Engine::StopAnimator() {
|
|
animator_->Stop();
|
|
}
|
|
|
|
void Engine::StartAnimatorIfPossible() {
|
|
if (activity_running_ && have_surface_)
|
|
animator_->Start();
|
|
}
|
|
|
|
void Engine::ScheduleFrame() {
|
|
animator_->RequestFrame();
|
|
}
|
|
|
|
mojo::NavigatorHost* Engine::NavigatorHost() {
|
|
return this;
|
|
}
|
|
|
|
void Engine::RequestNavigate(mojo::Target target,
|
|
mojo::URLRequestPtr request) {
|
|
// Ignoring target for now.
|
|
base::MessageLoop::current()->PostTask(
|
|
FROM_HERE,
|
|
base::Bind(&Engine::RunFromNetwork, GetWeakPtr(), request->url));
|
|
}
|
|
|
|
void Engine::DidNavigateLocally(const mojo::String& url) {
|
|
}
|
|
|
|
void Engine::RequestNavigateHistory(int32_t delta) {
|
|
NOTIMPLEMENTED();
|
|
}
|
|
|
|
} // namespace shell
|
|
} // namespace sky
|