engine.cc 12.3 KB
Newer Older
1 2 3 4 5 6
// 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"

A
Adam Barth 已提交
7
#include "base/bind.h"
8
#include "base/files/file_path.h"
9
#include "base/files/file_util.h"
10
#include "base/threading/worker_pool.h"
11
#include "base/time/time.h"
A
Adam Barth 已提交
12
#include "base/trace_event/trace_event.h"
13
#include "mojo/data_pipe_utils/data_pipe_utils.h"
14
#include "mojo/public/cpp/application/connect.h"
15
#include "services/asset_bundle/zip_asset_bundle.h"
A
Adam Barth 已提交
16
#include "sky/engine/bindings/mojo_services.h"
17
#include "sky/engine/core/script/dart_init.h"
18
#include "sky/engine/core/script/directory_asset_bundle.h"
19
#include "sky/engine/core/script/ui_dart_state.h"
20
#include "sky/engine/public/web/Sky.h"
21
#include "sky/shell/dart/dart_library_provider_files.h"
22
#include "sky/shell/shell.h"
A
Adam Barth 已提交
23
#include "sky/shell/ui/animator.h"
J
Jason Simmons 已提交
24
#include "sky/shell/ui/flutter_font_selector.h"
A
Adam Barth 已提交
25
#include "sky/shell/ui/platform_impl.h"
A
Adam Barth 已提交
26 27
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
28 29 30

namespace sky {
namespace shell {
31
namespace {
32

33 34
PlatformImpl* g_platform_impl = nullptr;

35 36
}  // namespace

37
using mojo::asset_bundle::ZipAssetBundle;
J
Jason Simmons 已提交
38
using mojo::asset_bundle::ZipAssetService;
E
Eric Seidel 已提交
39

40
Engine::Config::Config() {}
A
Adam Barth 已提交
41

42
Engine::Config::~Config() {}
A
Adam Barth 已提交
43

F
Florian Loitsch 已提交
44
Engine::Engine(const Config& config, rasterizer::RasterizerPtr rasterizer)
45
    : config_(config),
F
Florian Loitsch 已提交
46
      animator_(new Animator(config, rasterizer.Pass(), this)),
47
      binding_(this),
48 49
      activity_running_(false),
      have_surface_(false),
50
      weak_factory_(this) {}
51

52
Engine::~Engine() {}
53 54 55 56 57

base::WeakPtr<Engine> Engine::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

58
void Engine::Init() {
59
  TRACE_EVENT0("flutter", "Engine::Init");
A
Adam Barth 已提交
60

61 62 63
  DCHECK(!g_platform_impl);
  g_platform_impl = new PlatformImpl();
  blink::initialize(g_platform_impl);
64 65
}

A
Adam Barth 已提交
66
void Engine::BeginFrame(ftl::TimePoint frame_time) {
67
  TRACE_EVENT0("flutter", "Engine::BeginFrame");
68 69
  if (sky_view_)
    sky_view_->BeginFrame(frame_time);
A
Adam Barth 已提交
70 71
}

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
void Engine::RunFromSource(const std::string& main,
                           const std::string& packages,
                           const std::string& assets_directory) {
  TRACE_EVENT0("flutter", "Engine::RunFromSource");
  // Assets.
  base::FilePath assets_directory_path = base::FilePath(assets_directory);
  ConfigureDirectoryAssetBundle(assets_directory_path);
  // .packages.
  base::FilePath packages_path = base::FilePath(std::string(packages));
  if (packages_path.empty()) {
    base::FilePath main_dir = base::FilePath(main).DirName();
    packages_path = main_dir.Append(FILE_PATH_LITERAL(".packages"));
    if (!base::PathExists(packages_path)) {
      packages_path = main_dir.Append(base::FilePath::kParentDirectory)
                          .Append(FILE_PATH_LITERAL(".packages"));
      if (!base::PathExists(packages_path))
        packages_path = base::FilePath();
    }
  }
  DartLibraryProviderFiles* provider = new DartLibraryProviderFiles();
  dart_library_provider_.reset(provider);
  if (!packages_path.empty())
    provider->LoadPackagesMap(packages_path);
  RunFromLibrary(main);
}

98 99
void Engine::ConnectToEngine(mojo::InterfaceRequest<SkyEngine> request) {
  binding_.Bind(request.Pass());
100 101
}

A
Adam Barth 已提交
102 103
void Engine::OnOutputSurfaceCreated(const base::Closure& gpu_continuation) {
  config_.gpu_task_runner->PostTask(FROM_HERE, gpu_continuation);
104 105
  have_surface_ = true;
  StartAnimatorIfPossible();
106
  if (sky_view_)
107
    ScheduleFrame();
108 109
}

A
Adam Barth 已提交
110
void Engine::OnOutputSurfaceDestroyed(const base::Closure& gpu_continuation) {
111 112
  have_surface_ = false;
  StopAnimator();
A
Adam Barth 已提交
113
  config_.gpu_task_runner->PostTask(FROM_HERE, gpu_continuation);
114 115
}

116 117 118
void Engine::SetServices(ServicesDataPtr services) {
  services_ = services.Pass();

A
Adam Barth 已提交
119
  if (services_->incoming_services) {
A
Adam Barth 已提交
120 121
    incoming_services_ =
        mojo::ServiceProviderPtr::Create(services_->incoming_services.Pass());
122
    service_provider_impl_.set_fallback_service_provider(
A
Adam Barth 已提交
123
        incoming_services_.get());
124 125
  }

A
Adam Barth 已提交
126
  if (services_->frame_scheduler) {
127
    animator_->Reset();
A
Adam Barth 已提交
128
    animator_->set_frame_scheduler(services_->frame_scheduler.Pass());
A
Adam Barth 已提交
129
  } else {
A
Adam Barth 已提交
130 131 132
#if defined(OS_ANDROID) || defined(OS_IOS)
    vsync::VSyncProviderPtr vsync_provider;
    if (services_->shell) {
133 134 135
      // 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());
A
Adam Barth 已提交
136 137
      mojo::ConnectToService(shell.get(), "mojo:vsync",
                             mojo::GetProxy(&vsync_provider));
138
      services_->shell = shell.Pass();
A
Adam Barth 已提交
139
    } else {
A
Adam Barth 已提交
140 141
      mojo::ConnectToService(incoming_services_.get(),
                             mojo::GetProxy(&vsync_provider));
A
Adam Barth 已提交
142
    }
143
    animator_->Reset();
A
Adam Barth 已提交
144
    animator_->set_vsync_provider(vsync_provider.Pass());
145
#endif
A
Adam Barth 已提交
146
  }
147 148
}

A
Adam Barth 已提交
149
void Engine::OnViewportMetricsChanged(ViewportMetricsPtr metrics) {
150
  viewport_metrics_ = metrics.Pass();
A
Adam Barth 已提交
151
  if (sky_view_)
152
    sky_view_->SetViewportMetrics(viewport_metrics_);
153 154
}

155
void Engine::OnLocaleChanged(const mojo::String& language_code,
156
                             const mojo::String& country_code) {
157 158 159 160 161 162
  language_code_ = language_code;
  country_code_ = country_code;
  if (sky_view_)
    sky_view_->SetLocale(language_code_, country_code_);
}

163
void Engine::OnPointerPacket(pointer::PointerPacketPtr packet) {
164
  TRACE_EVENT0("flutter", "Engine::OnPointerPacket");
165 166 167

  // Convert the pointers' x and y coordinates to logical pixels.
  for (auto it = packet->pointers.begin(); it != packet->pointers.end(); ++it) {
168 169
    (*it)->x /= viewport_metrics_->device_pixel_ratio;
    (*it)->y /= viewport_metrics_->device_pixel_ratio;
170 171 172 173
  }

  if (sky_view_)
    sky_view_->HandlePointerPacket(packet);
174 175
}

176
void Engine::RunFromLibrary(const std::string& name) {
C
Chinmay Garde 已提交
177
  TRACE_EVENT0("flutter", "Engine::RunFromLibrary");
178
  sky_view_ = blink::SkyView::Create(this);
179 180
  sky_view_->CreateView(name);
  sky_view_->RunFromLibrary(name, dart_library_provider_.get());
181
  sky_view_->SetViewportMetrics(viewport_metrics_);
182
  sky_view_->SetLocale(language_code_, country_code_);
A
Adam Barth 已提交
183 184
  if (!initial_route_.empty())
    sky_view_->PushRoute(initial_route_);
185 186
}

187
void Engine::RunFromSnapshotStream(
188
    const std::string& script_uri,
189
    mojo::ScopedDataPipeConsumerHandle snapshot) {
190
  TRACE_EVENT0("flutter", "Engine::RunFromSnapshotStream");
191
  sky_view_ = blink::SkyView::Create(this);
192 193
  sky_view_->CreateView(script_uri);
  sky_view_->RunFromSnapshot(snapshot.Pass());
194
  sky_view_->SetViewportMetrics(viewport_metrics_);
195
  sky_view_->SetLocale(language_code_, country_code_);
A
Adam Barth 已提交
196 197
  if (!initial_route_.empty())
    sky_view_->PushRoute(initial_route_);
198 199
}

200 201 202 203 204 205
void Engine::ConfigureZipAssetBundle(const mojo::String& path) {
  zip_asset_bundle_ = new ZipAssetBundle(base::FilePath(std::string{path}),
                                         base::WorkerPool::GetTaskRunner(true));
  ZipAssetService::Create(mojo::GetProxy(&root_bundle_), zip_asset_bundle_);
}

206 207 208 209 210
void Engine::ConfigureDirectoryAssetBundle(const base::FilePath& path) {
  blink::DirectoryAssetBundleService::Create(
      mojo::GetProxy(&root_bundle_), path);
}

211
void Engine::RunFromPrecompiledSnapshot(const mojo::String& bundle_path) {
C
Chinmay Garde 已提交
212
  TRACE_EVENT0("flutter", "Engine::RunFromPrecompiledSnapshot");
213

214
  ConfigureZipAssetBundle(bundle_path);
215

216
  sky_view_ = blink::SkyView::Create(this);
217
  sky_view_->CreateView("http://localhost");
218
  sky_view_->RunFromPrecompiledSnapshot();
219
  sky_view_->SetViewportMetrics(viewport_metrics_);
220
  sky_view_->SetLocale(language_code_, country_code_);
A
Adam Barth 已提交
221 222
  if (!initial_route_.empty())
    sky_view_->PushRoute(initial_route_);
223 224
}

225
void Engine::RunFromFile(const mojo::String& main,
226
                         const mojo::String& packages,
227
                         const mojo::String& bundle) {
C
Chinmay Garde 已提交
228
  TRACE_EVENT0("flutter", "Engine::RunFromFile");
229
  std::string main_str(main);
230 231 232 233
  if (bundle.size() != 0) {
    // The specification of an FLX bundle is optional.
    ConfigureZipAssetBundle(bundle);
  }
234 235 236 237 238
  base::FilePath packages_path = base::FilePath(std::string(packages));
  if (packages_path.empty()) {
    base::FilePath main_dir = base::FilePath(main_str).DirName();
    packages_path = main_dir.Append(FILE_PATH_LITERAL(".packages"));
    if (!base::PathExists(packages_path)) {
A
Adam Barth 已提交
239 240
      packages_path = main_dir.Append(base::FilePath::kParentDirectory)
                          .Append(FILE_PATH_LITERAL(".packages"));
241 242 243 244 245 246 247 248 249
      if (!base::PathExists(packages_path))
        packages_path = base::FilePath();
    }
  }
  DartLibraryProviderFiles* provider = new DartLibraryProviderFiles();
  dart_library_provider_.reset(provider);
  if (!packages_path.empty())
    provider->LoadPackagesMap(packages_path);
  RunFromLibrary(main_str);
250 251
}

252 253
void Engine::RunFromBundle(const mojo::String& script_uri,
                           const mojo::String& path) {
254
  TRACE_EVENT0("flutter", "Engine::RunFromBundle");
255

256 257
  ConfigureZipAssetBundle(path);

A
Adam Barth 已提交
258 259 260
  root_bundle_->GetAsStream(blink::kSnapshotAssetKey,
                            base::Bind(&Engine::RunFromSnapshotStream,
                                       weak_factory_.GetWeakPtr(), script_uri));
261 262
}

263 264
void Engine::RunFromBundleAndSnapshot(const mojo::String& script_uri,
                                      const mojo::String& bundle_path,
265 266
                                      const mojo::String& snapshot_path) {
  TRACE_EVENT0("flutter", "Engine::RunFromBundleAndSnapshot");
267 268

  ConfigureZipAssetBundle(bundle_path);
269 270

  std::string snapshot_path_str = snapshot_path;
271
  zip_asset_bundle_->AddOverlayFile(blink::kSnapshotAssetKey,
J
Jason Simmons 已提交
272
                                    base::FilePath(snapshot_path_str));
273

A
Adam Barth 已提交
274 275 276
  root_bundle_->GetAsStream(blink::kSnapshotAssetKey,
                            base::Bind(&Engine::RunFromSnapshotStream,
                                       weak_factory_.GetWeakPtr(), script_uri));
277 278
}

A
Adam Barth 已提交
279 280 281 282 283 284 285 286 287 288 289 290
void Engine::PushRoute(const mojo::String& route) {
  if (sky_view_)
    sky_view_->PushRoute(route);
  else
    initial_route_ = route;
}

void Engine::PopRoute() {
  if (sky_view_)
    sky_view_->PopRoute();
}

291 292 293 294 295 296 297 298 299 300 301 302
void Engine::OnAppLifecycleStateChanged(sky::AppLifecycleState state) {
  switch (state) {
    case sky::AppLifecycleState::PAUSED:
      activity_running_ = false;
      StopAnimator();
      break;

    case sky::AppLifecycleState::RESUMED:
      activity_running_ = true;
      StartAnimatorIfPossible();
      break;
  }
303

304 305
  if (sky_view_)
    sky_view_->OnAppLifecycleStateChanged(state);
306 307
}

308 309 310 311 312
void Engine::DidCreateMainIsolate(Dart_Isolate isolate) {
  mojo::ServiceProviderPtr services_from_embedder;
  service_provider_bindings_.AddBinding(
      &service_provider_impl_, mojo::GetProxy(&services_from_embedder));

A
Adam Barth 已提交
313 314 315
  blink::MojoServices::Create(isolate, services_.Pass(),
                              services_from_embedder.Pass(),
                              root_bundle_.Pass());
J
Jason Simmons 已提交
316

317
  if (zip_asset_bundle_) {
J
Jason Simmons 已提交
318
    FlutterFontSelector::install(zip_asset_bundle_);
319
  }
320 321
}

322 323 324 325
void Engine::DidCreateSecondaryIsolate(Dart_Isolate isolate) {
  mojo::ServiceProviderPtr services_from_embedder;
  mojo::InterfaceRequest<mojo::ServiceProvider> request =
      mojo::GetProxy(&services_from_embedder);
326
  base::Closure closure =
A
Adam Barth 已提交
327
      base::Bind(&Engine::BindToServiceProvider, weak_factory_.GetWeakPtr(),
328 329 330
                 base::Passed(&request));
  blink::Platform::current()->GetUITaskRunner()->PostTask(
      [closure]() { closure.Run(); });
A
Adam Barth 已提交
331 332
  blink::MojoServices::Create(isolate, nullptr, services_from_embedder.Pass(),
                              nullptr);
333 334 335 336 337 338 339 340
}

void Engine::BindToServiceProvider(
    mojo::InterfaceRequest<mojo::ServiceProvider> request) {
  service_provider_bindings_.AddBinding(&service_provider_impl_,
                                        request.Pass());
}

341 342 343 344 345 346 347 348 349
void Engine::StopAnimator() {
  animator_->Stop();
}

void Engine::StartAnimatorIfPossible() {
  if (activity_running_ && have_surface_)
    animator_->Start();
}

350
void Engine::ScheduleFrame() {
A
Adam Barth 已提交
351 352 353
  animator_->RequestFrame();
}

354 355 356 357
void Engine::FlushRealTimeEvents() {
  animator_->FlushRealTimeEvents();
}

358 359 360 361 362
void Engine::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
  if (!layer_tree)
    return;
  if (viewport_metrics_) {
    layer_tree->set_scene_version(viewport_metrics_->scene_version);
A
Adam Barth 已提交
363 364
    layer_tree->set_frame_size(SkISize::Make(
        viewport_metrics_->physical_width, viewport_metrics_->physical_height));
365 366 367 368 369 370
  } else {
    layer_tree->set_scene_version(0);
    layer_tree->set_frame_size(SkISize::Make(0, 0));
  }
  animator_->Render(std::move(layer_tree));
}
371

372 373
}  // namespace shell
}  // namespace sky