| OLD | NEW |
| 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 "mojo/services/gfx/composition/cpp/formatting.h" |
| 8 #include "mojo/skia/type_converters.h" | 9 #include "mojo/skia/type_converters.h" |
| 9 #include "services/gfx/compositor/graph/scene_content.h" | 10 #include "services/gfx/compositor/graph/scene_content.h" |
| 10 #include "services/gfx/compositor/graph/scene_def.h" | |
| 11 #include "services/gfx/compositor/render/render_frame.h" | 11 #include "services/gfx/compositor/render/render_frame.h" |
| 12 #include "third_party/skia/include/core/SkPictureRecorder.h" | 12 #include "third_party/skia/include/core/SkPictureRecorder.h" |
| 13 #include "third_party/skia/include/core/SkRect.h" | 13 #include "third_party/skia/include/core/SkRect.h" |
| 14 #include "third_party/skia/include/utils/SkMatrix44.h" | 14 #include "third_party/skia/include/utils/SkMatrix44.h" |
| 15 | 15 |
| 16 namespace compositor { | 16 namespace compositor { |
| 17 | 17 |
| 18 Snapshot::Snapshot() {} | 18 Snapshot::Snapshot() {} |
| 19 | 19 |
| 20 Snapshot::~Snapshot() {} | 20 Snapshot::~Snapshot() {} |
| 21 | 21 |
| 22 bool Snapshot::HasDependency(const SceneDef* scene) const { | 22 bool Snapshot::HasDependency( |
| 23 return dependencies_.find(scene->label().token()) != dependencies_.end(); | 23 const mojo::gfx::composition::SceneToken& scene_token) const { |
| 24 return dependencies_.find(scene_token.value) != dependencies_.end(); |
| 24 } | 25 } |
| 25 | 26 |
| 26 scoped_refptr<RenderFrame> Snapshot::CreateFrame( | 27 scoped_refptr<RenderFrame> Snapshot::CreateFrame( |
| 27 const mojo::Rect& viewport, | 28 const mojo::Rect& viewport, |
| 28 const mojo::gfx::composition::FrameInfo& frame_info) const { | 29 const mojo::gfx::composition::FrameInfo& frame_info) const { |
| 29 DCHECK(!is_blocked()); | 30 DCHECK(!is_blocked()); |
| 30 DCHECK(root_scene_content_); | 31 DCHECK(root_scene_content_); |
| 31 | 32 |
| 32 SkIRect sk_viewport = viewport.To<SkIRect>(); | 33 SkIRect sk_viewport = viewport.To<SkIRect>(); |
| 33 | 34 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 61 const SceneContent* Snapshot::GetResolvedSceneContent( | 62 const SceneContent* Snapshot::GetResolvedSceneContent( |
| 62 const SceneNode* scene_node) const { | 63 const SceneNode* scene_node) const { |
| 63 DCHECK(!is_blocked()); | 64 DCHECK(!is_blocked()); |
| 64 | 65 |
| 65 auto it = resolved_scene_contents_.find(scene_node); | 66 auto it = resolved_scene_contents_.find(scene_node); |
| 66 DCHECK(it != resolved_scene_contents_.end()); | 67 DCHECK(it != resolved_scene_contents_.end()); |
| 67 return it->second.get(); | 68 return it->second.get(); |
| 68 } | 69 } |
| 69 | 70 |
| 70 SnapshotBuilder::SnapshotBuilder(std::ostream* block_log) | 71 SnapshotBuilder::SnapshotBuilder(std::ostream* block_log) |
| 71 : block_log_(block_log), snapshot_(new Snapshot()) {} | 72 : snapshot_(new Snapshot()), block_log_(block_log) {} |
| 72 | 73 |
| 73 SnapshotBuilder::~SnapshotBuilder() {} | 74 SnapshotBuilder::~SnapshotBuilder() {} |
| 74 | 75 |
| 75 Snapshot::Disposition SnapshotBuilder::SnapshotNode( | 76 Snapshot::Disposition SnapshotBuilder::SnapshotNode( |
| 76 const Node* node, | 77 const Node* node, |
| 77 const SceneContent* content) { | 78 const SceneContent* content) { |
| 78 DCHECK(snapshot_); | 79 DCHECK(snapshot_); |
| 79 DCHECK(node); | 80 DCHECK(node); |
| 80 DCHECK(content); | 81 DCHECK(content); |
| 81 DCHECK(node != content->GetRootNodeIfExists()); | |
| 82 | 82 |
| 83 auto it = snapshot_->node_dispositions_.find(node); | 83 auto it = snapshot_->node_dispositions_.find(node); |
| 84 if (it != snapshot_->node_dispositions_.end()) | 84 if (it != snapshot_->node_dispositions_.end()) |
| 85 return it->second; | 85 return it->second; |
| 86 | 86 |
| 87 Snapshot::Disposition disposition = node->RecordSnapshot(content, this); | 87 Snapshot::Disposition disposition = node->RecordSnapshot(content, this); |
| 88 snapshot_->node_dispositions_[node] = disposition; | 88 snapshot_->node_dispositions_[node] = disposition; |
| 89 return disposition; | 89 return disposition; |
| 90 } | 90 } |
| 91 | 91 |
| 92 Snapshot::Disposition SnapshotBuilder::SnapshotRootAndDetectCycles( | 92 Snapshot::Disposition SnapshotBuilder::SnapshotReferencedScene( |
| 93 const Node* node, | |
| 94 const SceneContent* content) { | |
| 95 DCHECK(snapshot_); | |
| 96 DCHECK(node); | |
| 97 DCHECK(content); | |
| 98 DCHECK(node == content->GetRootNodeIfExists()); | |
| 99 | |
| 100 auto storage = snapshot_->node_dispositions_.emplace( | |
| 101 node, Snapshot::Disposition::kCycle); | |
| 102 if (!storage.second) { | |
| 103 if (storage.first->second == Snapshot::Disposition::kCycle) | |
| 104 cycle_ = content; // start unwinding, remember where to stop | |
| 105 return storage.first->second; | |
| 106 } | |
| 107 | |
| 108 Snapshot::Disposition disposition = node->RecordSnapshot(content, this); | |
| 109 if (disposition == Snapshot::Disposition::kSuccess) { | |
| 110 snapshot_->node_dispositions_[node] = disposition; | |
| 111 return disposition; | |
| 112 } | |
| 113 | |
| 114 // We cannot reuse the iterator in |storage.first| because it may have | |
| 115 // been invalidated by the call to |RecordSnapshot| due to rehashing so | |
| 116 // we must look up the node again just in case. | |
| 117 snapshot_->node_dispositions_[node] = Snapshot::Disposition::kBlocked; | |
| 118 | |
| 119 if (disposition == Snapshot::Disposition::kCycle) { | |
| 120 DCHECK(cycle_); | |
| 121 if (block_log_) { | |
| 122 *block_log_ << "Scene blocked because it is part of a cycle: " | |
| 123 << content->FormattedLabel() << std::endl; | |
| 124 } | |
| 125 if (cycle_ == content) { | |
| 126 cycle_ = nullptr; // found the ouroboros tail, stop unwinding | |
| 127 disposition = Snapshot::Disposition::kBlocked; | |
| 128 } | |
| 129 } | |
| 130 return disposition; | |
| 131 } | |
| 132 Snapshot::Disposition SnapshotBuilder::SnapshotScene( | |
| 133 const SceneDef* scene, | |
| 134 uint32_t version, | |
| 135 const SceneNode* referrer_node, | 93 const SceneNode* referrer_node, |
| 136 const SceneContent* referrer_content) { | 94 const SceneContent* referrer_content) { |
| 137 DCHECK(snapshot_); | 95 DCHECK(snapshot_); |
| 138 DCHECK(scene); | |
| 139 DCHECK(referrer_node); | 96 DCHECK(referrer_node); |
| 140 DCHECK(referrer_content); | 97 DCHECK(referrer_content); |
| 141 | 98 |
| 142 // This function should only ever be called once when snapshotting the | 99 // This function should only ever be called once when snapshotting the |
| 143 // referring |SceneNode| at which point the result will be memoized | 100 // referring |SceneNode| at which point the result will be memoized |
| 144 // by |SnapshotNode| as usual so reentrance should not occur. | 101 // by |SnapshotNode| as usual so reentrance should not occur. |
| 145 DCHECK(snapshot_->resolved_scene_contents_.find(referrer_node) == | 102 DCHECK(snapshot_->resolved_scene_contents_.find(referrer_node) == |
| 146 snapshot_->resolved_scene_contents_.end()); | 103 snapshot_->resolved_scene_contents_.end()); |
| 147 | 104 |
| 148 snapshot_->dependencies_.insert(scene->label().token()); | 105 auto scene_resource = |
| 106 static_cast<const SceneResource*>(referrer_content->GetResource( |
| 107 referrer_node->scene_resource_id(), Resource::Type::kScene)); |
| 108 DCHECK(scene_resource); |
| 149 | 109 |
| 150 const SceneContent* content = scene->FindContent(version); | 110 scoped_refptr<const SceneContent> content; |
| 151 if (!content) { | 111 Snapshot::Disposition disposition = AddDependencyResolveAndSnapshotScene( |
| 112 scene_resource->scene_token(), referrer_node->scene_version(), &content); |
| 113 |
| 114 if (disposition == Snapshot::Disposition::kSuccess) { |
| 115 snapshot_->resolved_scene_contents_[referrer_node] = content; |
| 116 } else if (disposition == Snapshot::Disposition::kBlocked) { |
| 152 if (block_log_) { | 117 if (block_log_) { |
| 153 *block_log_ << "Scene node blocked because its referenced scene is not " | 118 *block_log_ << "Scene node's referenced scene is blocked: " |
| 154 "available with the requested version: " | |
| 155 << referrer_node->FormattedLabel(referrer_content) | 119 << referrer_node->FormattedLabel(referrer_content) |
| 156 << ", scene " << scene->label().FormattedLabel() | 120 << ", referenced scene " << scene_resource->scene_token() |
| 157 << ", requested version " << version << ", current version " | 121 << ", version " << referrer_node->scene_version() |
| 158 << scene->version() << std::endl; | 122 << std::endl; |
| 123 } |
| 124 } |
| 125 return disposition; |
| 126 } |
| 127 |
| 128 Snapshot::Disposition SnapshotBuilder::SnapshotSceneContent( |
| 129 const SceneContent* content) { |
| 130 DCHECK(snapshot_); |
| 131 DCHECK(content); |
| 132 |
| 133 const Node* root = content->GetRootNodeIfExists(); |
| 134 if (!root) { |
| 135 if (block_log_) { |
| 136 *block_log_ << "Scene has no root node: " << content->FormattedLabel() |
| 137 << std::endl; |
| 159 } | 138 } |
| 160 return Snapshot::Disposition::kBlocked; | 139 return Snapshot::Disposition::kBlocked; |
| 161 } | 140 } |
| 162 | 141 |
| 163 const Node* root = content->GetRootNodeIfExists(); | 142 return SnapshotNode(root, content); |
| 164 if (!root) { | |
| 165 if (block_log_) { | |
| 166 *block_log_ << "Scene node blocked because its referenced scene has no " | |
| 167 "root node: " | |
| 168 << referrer_node->FormattedLabel(referrer_content) | |
| 169 << ", scene " << content->FormattedLabel() << std::endl; | |
| 170 } | |
| 171 return Snapshot::Disposition::kBlocked; | |
| 172 } | |
| 173 | |
| 174 snapshot_->resolved_scene_contents_[referrer_node] = content; | |
| 175 return SnapshotRootAndDetectCycles(root, content); | |
| 176 } | 143 } |
| 177 | 144 |
| 178 Snapshot::Disposition SnapshotBuilder::SnapshotRenderer(const SceneDef* scene) { | 145 Snapshot::Disposition SnapshotBuilder::AddDependencyResolveAndSnapshotScene( |
| 179 DCHECK(!snapshot_->root_scene_content_); | 146 const mojo::gfx::composition::SceneToken& scene_token, |
| 147 uint32_t version, |
| 148 scoped_refptr<const SceneContent>* out_content) { |
| 149 DCHECK(out_content); |
| 180 | 150 |
| 181 snapshot_->dependencies_.insert(scene->label().token()); | 151 snapshot_->dependencies_.insert(scene_token.value); |
| 182 | 152 return ResolveAndSnapshotScene(scene_token, version, out_content); |
| 183 const SceneContent* content = | |
| 184 scene->FindContent(mojo::gfx::composition::kSceneVersionNone); | |
| 185 if (!content) { | |
| 186 if (block_log_) { | |
| 187 *block_log_ << "Rendering blocked because the root scene has no content: " | |
| 188 << scene->label().FormattedLabel() << std::endl; | |
| 189 } | |
| 190 return Snapshot::Disposition::kBlocked; | |
| 191 } | |
| 192 | |
| 193 const Node* root = content->GetRootNodeIfExists(); | |
| 194 if (!root) { | |
| 195 if (block_log_) { | |
| 196 *block_log_ << "Rendering blocked the root scene has no root node: " | |
| 197 << content->FormattedLabel() << std::endl; | |
| 198 } | |
| 199 return Snapshot::Disposition::kBlocked; | |
| 200 } | |
| 201 | |
| 202 snapshot_->root_scene_content_ = content; | |
| 203 return SnapshotRootAndDetectCycles(root, content); | |
| 204 } | 153 } |
| 205 | 154 |
| 206 scoped_refptr<const Snapshot> SnapshotBuilder::Build( | 155 scoped_refptr<const Snapshot> SnapshotBuilder::Build( |
| 207 const SceneDef* root_scene) { | 156 const mojo::gfx::composition::SceneToken& scene_token, |
| 157 uint32_t version) { |
| 208 DCHECK(snapshot_); | 158 DCHECK(snapshot_); |
| 209 DCHECK(root_scene); | 159 DCHECK(!snapshot_->root_scene_content_); |
| 210 | 160 |
| 211 snapshot_->disposition_ = SnapshotRenderer(root_scene); | 161 scoped_refptr<const SceneContent> content; |
| 212 DCHECK(!cycle_); // must have properly unwound any cycles by now | 162 snapshot_->disposition_ = |
| 163 AddDependencyResolveAndSnapshotScene(scene_token, version, &content); |
| 213 | 164 |
| 214 if (snapshot_->is_blocked()) { | 165 if (!snapshot_->is_blocked()) { |
| 215 snapshot_->root_scene_content_ = nullptr; | 166 snapshot_->root_scene_content_ = content; |
| 167 } else { |
| 216 snapshot_->resolved_scene_contents_.clear(); | 168 snapshot_->resolved_scene_contents_.clear(); |
| 217 snapshot_->node_dispositions_.clear(); | 169 snapshot_->node_dispositions_.clear(); |
| 218 } | 170 } |
| 219 return std::move(snapshot_); | 171 return std::move(snapshot_); |
| 220 } | 172 } |
| 221 | 173 |
| 222 } // namespace compositor | 174 } // namespace compositor |
| OLD | NEW |