Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: services/gfx/compositor/graph/universe.cc

Issue 1873573003: Mozart: Ensure time always runs forward. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-3
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « services/gfx/compositor/graph/universe.h ('k') | services/gfx/compositor/scene_state.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/gfx/compositor/graph/universe.h"
6
7 #include "base/logging.h"
8 #include "mojo/services/gfx/composition/cpp/formatting.h"
9 #include "services/gfx/compositor/graph/scene_content.h"
10
11 namespace compositor {
12
13 Universe::Universe() {}
14
15 Universe::~Universe() {}
16
17 void Universe::AddScene(const SceneLabel& label) {
18 auto it = scenes_.find(label.token());
abarth 2016/04/08 03:13:50 I'd move the find into the DCHECK
jeffbrown 2016/04/08 03:35:20 Done.
19 DCHECK(it == scenes_.end());
20 scenes_.emplace(label.token(),
21 std::unique_ptr<SceneInfo>(new SceneInfo(label)));
22 }
23
24 void Universe::PresentScene(const scoped_refptr<const SceneContent>& content) {
25 auto it = scenes_.find(content->label().token());
26 DCHECK(it != scenes_.end());
27 it->second->content_queue.emplace_front(content);
28 }
29
30 void Universe::RemoveScene(
31 const mojo::gfx::composition::SceneToken& scene_token) {
32 auto it = scenes_.find(scene_token.value);
33 DCHECK(it != scenes_.end());
34 scenes_.erase(it);
35 }
36
37 scoped_refptr<const Snapshot> Universe::SnapshotScene(
38 const mojo::gfx::composition::SceneToken& scene_token,
39 uint32_t version,
40 std::ostream* block_log) {
41 generation_++;
42 CHECK(generation_);
43
44 Snapshotter snapshotter(this, block_log);
45 scoped_refptr<const Snapshot> snapshot =
46 snapshotter.Build(scene_token, version);
47
48 // TODO(jeffbrown): Find a better way to prune unused scene versions.
49 // This logic is expensive and will break if there are multiple renderers
50 // involved. Perhaps we should do something like say that all renderers
51 // that live in the same universe should get snapshotted simultaneously.
52 // Or maybe we could be smarter and partition scenes by reachability
53 // using some heuristics to decide which partition should be the scene's
54 // "primary" in case of conflict (so that scenes which only appear on a
55 // single display can be rate-coupled to that display whereas those that
56 // appear in multiple places might experience some resampling).
57 // There's a similar problem lurking in the scheduler mechanism.
58 for (const auto& pair : scenes_) {
59 SceneInfo* info = pair.second.get();
60 if (info->update_generation != generation_ &&
61 info->content_queue.size() > 1) {
62 info->content_queue.erase(info->content_queue.begin() + 1,
63 info->content_queue.end());
64 }
65 }
66 return snapshot;
67 }
68
69 Universe::SceneInfo::SceneInfo(const SceneLabel& label) : label(label) {}
70
71 Universe::SceneInfo::~SceneInfo() {}
72
73 Universe::Snapshotter::Snapshotter(Universe* universe, std::ostream* block_log)
74 : SnapshotBuilder(block_log), universe_(universe) {
75 DCHECK(universe_);
76 }
77
78 Universe::Snapshotter::~Snapshotter() {
79 DCHECK(!cycle_); // must have properly unwound any cycles by now
80 }
81
82 Snapshot::Disposition Universe::Snapshotter::ResolveAndSnapshotScene(
83 const mojo::gfx::composition::SceneToken& scene_token,
84 uint32_t version,
85 scoped_refptr<const SceneContent>* out_content) {
86 auto it = universe_->scenes_.find(scene_token.value);
87 if (it == universe_->scenes_.end()) {
88 if (block_log()) {
89 *block_log() << "Scene not available: " << scene_token << std::endl;
90 }
91 return Snapshot::Disposition::kBlocked;
92 }
93
94 // TODO(jeffbrown): Ok, this logic is downright terrible. It will end
95 // up doing N^2 work when things are blocked. Replace this with some kind
96 // of sane invalidation mechanism before the system explodes.
97 SceneInfo* info = it->second.get();
98 if (info->update_generation == universe_->generation_) {
99 if (info->disposition == Snapshot::Disposition::kCycle) {
100 cycle_ = info; // start unwinding, remember where to stop
101 return Snapshot::Disposition::kCycle;
102 }
103 if (info->disposition == Snapshot::Disposition::kBlocked) {
104 if (block_log()) {
105 *block_log() << "Scene blocked (cached prior disposition): "
106 << info->label.FormattedLabel() << std::endl;
107 }
108 return Snapshot::Disposition::kBlocked;
109 }
110 } else {
111 info->update_generation = universe_->generation_;
112 if (info->content_queue.empty()) {
113 if (block_log()) {
114 *block_log() << "Scene has not presented any content: "
115 << info->label.FormattedLabel() << std::endl;
116 }
117 info->disposition = Snapshot::Disposition::kBlocked;
118 return Snapshot::Disposition::kBlocked;
119 }
120
121 auto it = info->content_queue.begin();
122 for (;;) {
123 info->disposition = Snapshot::Disposition::kCycle;
124 info->disposition = SnapshotSceneContent((*it).get());
125 if (info->disposition == Snapshot::Disposition::kSuccess)
126 break;
127 if (info->disposition == Snapshot::Disposition::kCycle) {
128 DCHECK(cycle_);
129 if (block_log()) {
130 *block_log() << "Scene is part of a cycle: "
131 << (*it)->FormattedLabel() << std::endl;
132 }
133 if (cycle_ == info)
134 cycle_ = nullptr; // found the ouroboros tail, stop unwinding
135 info->disposition = Snapshot::Disposition::kBlocked;
136 return Snapshot::Disposition::kCycle;
137 }
138 if (++it == info->content_queue.end())
139 return Snapshot::Disposition::kBlocked;
140 }
141 if (it + 1 != info->content_queue.end())
142 info->content_queue.erase(it + 1, info->content_queue.end());
143 }
144
145 DCHECK(info->disposition == Snapshot::Disposition::kSuccess);
146 DCHECK(!info->content_queue.empty());
147 const scoped_refptr<const SceneContent>& content = info->content_queue.back();
148 if (!content->MatchesVersion(version)) {
149 if (block_log()) {
150 *block_log() << "Scene version mismatch: " << info->label.FormattedLabel()
151 << ", requested version " << version
152 << ", available version " << content->version() << std::endl;
153 }
154 return Snapshot::Disposition::kBlocked;
155 }
156
157 *out_content = content;
158 return Snapshot::Disposition::kSuccess;
159 }
160
161 } // namespace compositor
OLDNEW
« no previous file with comments | « services/gfx/compositor/graph/universe.h ('k') | services/gfx/compositor/scene_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698