forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vulkan_rasterizer.cc
119 lines (97 loc) · 3.4 KB
/
vulkan_rasterizer.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2017 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/content_handler/vulkan_rasterizer.h"
#include <fcntl.h>
#include <magenta/device/vfs.h>
#include <mxio/watcher.h>
#include <unistd.h>
#include <chrono>
#include <thread>
#include <utility>
#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "lib/ftl/files/unique_fd.h"
namespace flutter_runner {
constexpr char kDisplayDriverClass[] = "/dev/class/display";
static mx_status_t DriverWatcher(int dirfd,
int event,
const char* fn,
void* cookie) {
if (event == WATCH_EVENT_ADD_FILE && !strcmp(fn, "000")) {
return MX_ERR_STOP;
}
return MX_OK;
}
bool WaitForFirstDisplayDriver() {
ftl::UniqueFD fd(open(kDisplayDriverClass, O_DIRECTORY | O_RDONLY));
if (fd.get() < 0) {
FTL_DLOG(ERROR) << "Failed to open " << kDisplayDriverClass;
return false;
}
mx_status_t status = mxio_watch_directory(
fd.get(), DriverWatcher, mx_deadline_after(MX_SEC(1)), nullptr);
return status == MX_ERR_STOP;
}
VulkanRasterizer::VulkanRasterizer() : compositor_context_(nullptr) {
valid_ = WaitForFirstDisplayDriver();
}
VulkanRasterizer::~VulkanRasterizer() = default;
bool VulkanRasterizer::IsValid() const {
return valid_;
}
void VulkanRasterizer::SetScene(
fidl::InterfaceHandle<mozart2::SceneManager> scene_manager,
mx::eventpair import_token,
ftl::Closure metrics_changed_callback) {
ASSERT_IS_GPU_THREAD;
FTL_DCHECK(valid_ && !session_connection_);
session_connection_ = std::make_unique<SessionConnection>(
mozart2::SceneManagerPtr::Create(std::move(scene_manager)),
std::move(import_token));
session_connection_->set_metrics_changed_callback(
std::move(metrics_changed_callback));
}
void VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
ftl::Closure callback) {
ASSERT_IS_GPU_THREAD;
FTL_DCHECK(callback != nullptr);
if (layer_tree == nullptr) {
FTL_LOG(ERROR) << "Layer tree was not valid.";
callback();
return;
}
if (!session_connection_) {
FTL_LOG(ERROR) << "Session was not valid.";
callback();
return;
}
if (!session_connection_->has_metrics()) {
// Still awaiting metrics. Will redraw when we get them.
callback();
return;
}
compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());
flow::CompositorContext::ScopedFrame frame = compositor_context_.AcquireFrame(
nullptr, nullptr, true /* instrumentation enabled */);
{
// Preroll the Flutter layer tree. This allows Flutter to perform pre-paint
// optimizations.
TRACE_EVENT0("flutter", "Preroll");
layer_tree->Preroll(frame);
}
{
// Traverse the Flutter layer tree so that the necessary session ops to
// represent the frame are enqueued in the underlying session.
TRACE_EVENT0("flutter", "UpdateScene");
layer_tree->UpdateScene(session_connection_->scene_update_context(),
session_connection_->root_node());
}
{
// Flush all pending session ops.
TRACE_EVENT0("flutter", "SessionPresent");
session_connection_->Present(
frame, [callback = std::move(callback)]() { callback(); });
}
}
} // namespace flutter_runner