Chromium Code Reviews| Index: services/gfx/compositor/graph/scene_content.cc |
| diff --git a/services/gfx/compositor/graph/scene_content.cc b/services/gfx/compositor/graph/scene_content.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f5ce9b55cc5666591616f95341f1ae3fc2d8f1aa |
| --- /dev/null |
| +++ b/services/gfx/compositor/graph/scene_content.cc |
| @@ -0,0 +1,135 @@ |
| +// Copyright 2016 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 "services/gfx/compositor/graph/scene_content.h" |
| + |
| +#include <ostream> |
| + |
| +#include "base/logging.h" |
| +#include "services/gfx/compositor/graph/scene_def.h" |
| + |
| +namespace compositor { |
| + |
| +SceneContent::SceneContent(const SceneLabel& label, |
| + uint32_t version, |
| + size_t max_resources, |
| + size_t max_nodes) |
| + : label_(label), |
| + version_(version), |
| + resources_(max_resources), |
| + nodes_(max_nodes) {} |
| + |
| +SceneContent::~SceneContent() {} |
| + |
| +const ResourceDef* SceneContent::GetResource( |
| + uint32_t resource_id, |
| + ResourceDef::Type resource_type) const { |
| + auto it = resources_.find(resource_id); |
| + DCHECK(it != resources_.end()); |
| + DCHECK(it->second->type() == resource_type); |
| + return it->second.get(); |
| +} |
| + |
| +const NodeDef* SceneContent::GetNode(uint32_t node_id) const { |
| + auto it = nodes_.find(node_id); |
| + DCHECK(it != nodes_.end()); |
| + return it->second.get(); |
| +} |
| + |
| +const NodeDef* SceneContent::GetRootNodeIfExists() const { |
| + auto it = nodes_.find(mojo::gfx::composition::kSceneRootNodeId); |
| + return it != nodes_.end() ? it->second.get() : nullptr; |
| +} |
| + |
| +SceneContentBuilder::SceneContentBuilder(const SceneDef* scene, |
| + uint32_t version, |
| + std::ostream& err, |
| + size_t max_resources, |
| + size_t max_nodes) |
| + : content_( |
| + new SceneContent(scene->label(), version, max_resources, max_nodes)), |
| + scene_(scene), |
| + err_(err) { |
| + DCHECK(scene); |
| +} |
| + |
| +SceneContentBuilder::~SceneContentBuilder() {} |
| + |
| +const ResourceDef* SceneContentBuilder::RequireResource( |
| + uint32_t resource_id, |
| + ResourceDef::Type resource_type, |
| + uint32_t referrer_node_id) { |
| + DCHECK(content_); |
| + |
| + auto it = content_->resources_.find(resource_id); |
| + if (it != content_->resources_.end()) |
| + return it->second.get(); // found |
|
abarth
2016/03/01 17:21:26
I'd skip this comment. It's a common pattern for
jeffbrown
2016/03/02 00:32:16
Done.
|
| + |
| + const ResourceDef* resource = scene_->FindResource(resource_id); |
| + if (!resource) { |
| + err_ << "Missing resource " << resource_id << " referenced from node " |
| + << content_->FormattedLabelForNode(referrer_node_id); |
| + return nullptr; |
| + } |
| + |
| + if (resource->type() != resource_type) { |
| + err_ << "Resource " << resource_id << " referenced from node " |
| + << content_->FormattedLabelForNode(referrer_node_id) |
| + << " has incorrect type for its intended usage"; |
| + return nullptr; |
| + } |
| + |
| + content_->resources_.emplace(std::make_pair(resource_id, resource)); |
| + return resource; |
| +} |
| + |
| +const NodeDef* SceneContentBuilder::RequireNode(uint32_t node_id, |
| + uint32_t referrer_node_id) { |
| + DCHECK(content_); |
| + |
| + auto it = content_->nodes_.find(node_id); |
| + if (it != content_->nodes_.end()) { |
| + if (it->second) |
| + return it->second.get(); // already added |
| + err_ << "Cycle detected at node " << node_id << " referenced from node " |
| + << content_->FormattedLabelForNode(referrer_node_id); |
| + return nullptr; |
| + } |
| + |
| + const NodeDef* node = scene_->FindNode(node_id); |
| + if (!node) { |
| + err_ << "Missing node " << node_id << " referenced from node " |
| + << content_->FormattedLabelForNode(referrer_node_id); |
| + return nullptr; |
| + } |
| + |
| + return AddNode(node) ? node : nullptr; |
| +} |
| + |
| +bool SceneContentBuilder::AddNode(const NodeDef* node) { |
| + DCHECK(content_); |
| + DCHECK(node); |
| + |
| + // Reserve a spot in the table to mark the node recording in progress. |
| + content_->nodes_.emplace(std::make_pair(node->node_id(), nullptr)); |
| + |
| + // Record the node's content. |
| + // This performs a depth first search of the node. If it succeeds, we |
| + // will know that this part of the graph has no cycles. |
| + if (!node->RecordContent(this)) |
| + return false; |
| + |
| + // Store the node in the table. |
| + content_->nodes_[node->node_id()] = node; |
|
abarth
2016/03/01 17:21:26
There's a pattern for doing this without doing two
jeffbrown
2016/03/02 00:32:16
You're correct that we can do this but the reasons
|
| + return true; |
| +} |
| + |
| +scoped_refptr<const SceneContent> SceneContentBuilder::Build() { |
| + DCHECK(content_); |
| + |
| + const NodeDef* root = scene_->FindRootNode(); |
| + return !root || AddNode(root) ? std::move(content_) : nullptr; |
| +} |
| + |
| +} // namespace compositor |