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

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

Issue 1749063002: Mozart: Improve internal scene graph representation. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-0
Patch Set: Created 4 years, 9 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/gfx/compositor/graph/snapshot.h" 5 #include "services/gfx/compositor/graph/snapshot.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "services/gfx/compositor/graph/scene_content.h"
8 #include "services/gfx/compositor/graph/scene_def.h" 9 #include "services/gfx/compositor/graph/scene_def.h"
9 #include "services/gfx/compositor/render/render_frame.h" 10 #include "services/gfx/compositor/render/render_frame.h"
10 #include "services/gfx/compositor/render/render_layer.h" 11 #include "third_party/skia/include/core/SkPictureRecorder.h"
11 #include "third_party/skia/include/core/SkRect.h" 12 #include "third_party/skia/include/core/SkRect.h"
12 13
13 namespace compositor { 14 namespace compositor {
14 15
15 Snapshot::Snapshot() {} 16 Snapshot::Snapshot() {}
16 17
17 Snapshot::~Snapshot() {} 18 Snapshot::~Snapshot() {}
18 19
19 bool Snapshot::Invalidate() { 20 bool Snapshot::Invalidate() {
20 if (valid_) { 21 if (valid_) {
21 valid_ = false; 22 valid_ = false;
22 dependencies_.clear(); 23 dependencies_.clear();
23 frame_.reset(); 24 ClearContent();
24 return true; 25 return true;
25 } 26 }
26 return false; 27 return false;
27 } 28 }
28 29
29 bool Snapshot::InvalidateScene(SceneDef* scene_def) { 30 bool Snapshot::InvalidateScene(const SceneDef* scene_def) {
30 DCHECK(scene_def); 31 DCHECK(scene_def);
32 return valid_ &&
33 dependencies_.find(scene_def->label().token()) !=
34 dependencies_.end() &&
35 Invalidate();
36 }
31 37
32 if (valid_ && dependencies_.find(scene_def) != dependencies_.end()) { 38 void Snapshot::ClearContent() {
33 return Invalidate(); 39 root_scene_content_ = nullptr;
34 } 40 resolved_scene_contents_.clear();
35 return false; 41 node_dispositions_.clear();
42 frame_.reset();
43 }
44
45 bool Snapshot::IsBlocked(const NodeDef* node) const {
46 DCHECK(valid_);
47 auto it = node_dispositions_.find(node);
48 DCHECK(it != node_dispositions_.end());
49 DCHECK(it->second == Disposition::kSuccess ||
50 it->second == Disposition::kBlocked);
51 return it->second == Disposition::kBlocked;
52 }
53
54 const SceneContent* Snapshot::GetResolvedSceneContent(
55 const SceneNodeDef* scene_node) const {
56 DCHECK(valid_);
57 auto it = resolved_scene_contents_.find(scene_node);
58 DCHECK(it != resolved_scene_contents_.end());
59 return it->second.get();
36 } 60 }
37 61
38 SnapshotBuilder::SnapshotBuilder(std::ostream* block_log) 62 SnapshotBuilder::SnapshotBuilder(std::ostream* block_log)
39 : block_log_(block_log), snapshot_(new Snapshot()) {} 63 : block_log_(block_log), snapshot_(new Snapshot()) {}
40 64
41 SnapshotBuilder::~SnapshotBuilder() {} 65 SnapshotBuilder::~SnapshotBuilder() {}
42 66
43 void SnapshotBuilder::AddSceneDependency(SceneDef* scene) { 67 Snapshot::Disposition SnapshotBuilder::SnapshotNode(
68 const NodeDef* node,
69 const SceneContent* content) {
44 DCHECK(snapshot_); 70 DCHECK(snapshot_);
45 snapshot_->dependencies_.insert(scene); 71 DCHECK(node);
72 DCHECK(content);
73 DCHECK(node != content->GetRootNodeIfExists());
74
75 auto it = snapshot_->node_dispositions_.find(node);
76 if (it != snapshot_->node_dispositions_.end())
77 return it->second;
78
79 Snapshot::Disposition disposition = node->RecordSnapshot(content, this);
80 snapshot_->node_dispositions_[node] = disposition;
81 return disposition;
82 }
83
84 Snapshot::Disposition SnapshotBuilder::SnapshotRootAndDetectCycles(
85 const NodeDef* node,
86 const SceneContent* content) {
87 DCHECK(snapshot_);
88 DCHECK(node);
89 DCHECK(content);
90 DCHECK(node == content->GetRootNodeIfExists());
91
92 auto it = snapshot_->node_dispositions_.find(node);
93 if (it != snapshot_->node_dispositions_.end()) {
94 if (it->second == Snapshot::Disposition::kCycle)
95 cycle_ = content; // start unwinding, remember where to stop
96 return it->second;
97 }
98
99 snapshot_->node_dispositions_[node] = Snapshot::Disposition::kCycle;
abarth 2016/03/01 17:21:26 There's also a pattern for doing this with one has
jeffbrown 2016/03/02 00:32:16 True. Note that here rehashing may occur after th
100
101 Snapshot::Disposition disposition = node->RecordSnapshot(content, this);
102 if (disposition == Snapshot::Disposition::kSuccess) {
103 snapshot_->node_dispositions_[node] = disposition;
104 return disposition;
105 }
106
107 snapshot_->node_dispositions_[node] = Snapshot::Disposition::kBlocked;
108
109 if (disposition == Snapshot::Disposition::kCycle) {
110 DCHECK(cycle_);
111 if (block_log_) {
112 *block_log_ << "Scene blocked because it is part of a cycle: "
113 << content->FormattedLabel() << std::endl;
114 }
115 if (cycle_ == content) {
116 cycle_ = nullptr; // found the ouroboros tail, stop unwinding
117 disposition = Snapshot::Disposition::kBlocked;
118 }
119 }
120 return disposition;
121 }
122 Snapshot::Disposition SnapshotBuilder::SnapshotScene(
123 const SceneDef* scene,
124 uint32_t version,
125 const SceneNodeDef* referrer_node,
126 const SceneContent* referrer_content) {
127 DCHECK(snapshot_);
128 DCHECK(scene);
129 DCHECK(referrer_node);
130 DCHECK(referrer_content);
131
132 // This function should only ever be called once when snapshotting the
133 // referring |SceneNodeDef| at which point the result will be memoized
134 // by |SnapshotNode| as usual so reentrance should not occur.
135 DCHECK(snapshot_->resolved_scene_contents_.find(referrer_node) ==
136 snapshot_->resolved_scene_contents_.end());
137
138 snapshot_->dependencies_.insert(scene->label().token());
139
140 const SceneContent* content = scene->FindContent(version);
141 if (!content) {
142 if (block_log_) {
143 *block_log_ << "Scene node blocked because its referenced scene is not "
144 "available with the requested version: "
145 << referrer_node->FormattedLabel(referrer_content)
146 << ", scene " << scene->label().FormattedLabel()
147 << ", requested version " << version << ", current version "
148 << scene->version() << std::endl;
149 }
150 return Snapshot::Disposition::kBlocked;
151 }
152
153 const NodeDef* root = content->GetRootNodeIfExists();
154 if (!root) {
155 if (block_log_) {
156 *block_log_ << "Scene node blocked because its referenced scene has no "
157 "root node: "
158 << referrer_node->FormattedLabel(referrer_content)
159 << ", scene " << content->FormattedLabel() << std::endl;
160 }
161 return Snapshot::Disposition::kBlocked;
162 }
163
164 snapshot_->resolved_scene_contents_[referrer_node] = content;
165 return SnapshotRootAndDetectCycles(root, content);
166 }
167
168 Snapshot::Disposition SnapshotBuilder::SnapshotRenderer(const SceneDef* scene) {
169 DCHECK(!snapshot_->root_scene_content_);
170
171 snapshot_->dependencies_.insert(scene->label().token());
172
173 const SceneContent* content =
174 scene->FindContent(mojo::gfx::composition::kSceneVersionNone);
175 if (!content) {
176 if (block_log_) {
177 *block_log_ << "Rendering blocked because the root scene has no content: "
178 << scene->label().FormattedLabel() << std::endl;
179 }
180 return Snapshot::Disposition::kBlocked;
181 }
182
183 const NodeDef* root = content->GetRootNodeIfExists();
184 if (!root) {
185 if (block_log_) {
186 *block_log_ << "Rendering blocked the root scene has no root node: "
187 << content->FormattedLabel() << std::endl;
188 }
189 return Snapshot::Disposition::kBlocked;
190 }
191
192 snapshot_->root_scene_content_ = content;
193 return SnapshotRootAndDetectCycles(root, content);
46 } 194 }
47 195
48 std::unique_ptr<Snapshot> SnapshotBuilder::Build( 196 std::unique_ptr<Snapshot> SnapshotBuilder::Build(
49 SceneDef* root_scene, 197 const SceneDef* root_scene,
50 const mojo::Rect& viewport, 198 const mojo::Rect& viewport,
51 const mojo::gfx::composition::FrameInfo& frame_info) { 199 const mojo::gfx::composition::FrameInfo& frame_info) {
52 DCHECK(snapshot_); 200 DCHECK(snapshot_);
53 DCHECK(root_scene); 201 DCHECK(root_scene);
54 202
55 SkRect sk_viewport = 203 Snapshot::Disposition disposition = SnapshotRenderer(root_scene);
56 SkRect::MakeXYWH(viewport.x, viewport.y, viewport.width, viewport.height); 204 DCHECK(!cycle_); // must have properly unwound any cycles by now
57 RenderLayerBuilder layer_builder(&sk_viewport); 205
58 if (root_scene->Snapshot(this, &layer_builder)) { 206 if (disposition == Snapshot::Disposition::kSuccess) {
207 SkRect sk_viewport = SkRect::MakeXYWH(viewport.x, viewport.y,
208 viewport.width, viewport.height);
209 SkPictureRecorder recorder;
210 recorder.beginRecording(sk_viewport);
211
212 const NodeDef* root_node =
213 snapshot_->root_scene_content_->GetRootNodeIfExists();
214 DCHECK(root_node); // otherwise would have failed to snapshot
215 root_node->RecordPicture(snapshot_->root_scene_content_.get(),
216 snapshot_.get(), recorder.getRecordingCanvas());
217
59 snapshot_->frame_ = 218 snapshot_->frame_ =
60 RenderFrame::Create(layer_builder.Build(), sk_viewport, frame_info); 219 RenderFrame::Create(skia::AdoptRef(recorder.endRecordingAsPicture()),
220 sk_viewport, frame_info);
61 } else { 221 } else {
62 snapshot_->valid_ = false; 222 snapshot_->ClearContent();
63 } 223 }
64 return std::move(snapshot_); 224 return std::move(snapshot_);
65 } 225 }
66 226
67 } // namespace compositor 227 } // namespace compositor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698