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

Unified Diff: services/gfx/compositor/graph/scene_def.cc

Issue 1749063002: Mozart: Improve internal scene graph representation. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-0
Patch Set: avoid unnecessary hashtable lookups Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « services/gfx/compositor/graph/scene_def.h ('k') | services/gfx/compositor/graph/scene_label.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: services/gfx/compositor/graph/scene_def.cc
diff --git a/services/gfx/compositor/graph/scene_def.cc b/services/gfx/compositor/graph/scene_def.cc
index a23c1088a2376bb4d1a43442fe92e1a62f808248..649c43e8a76ee6362758014d5682353dbe847602 100644
--- a/services/gfx/compositor/graph/scene_def.cc
+++ b/services/gfx/compositor/graph/scene_def.cc
@@ -5,16 +5,14 @@
#include "services/gfx/compositor/graph/scene_def.h"
#include <ostream>
-#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "mojo/services/gfx/composition/cpp/formatting.h"
-#include "services/gfx/compositor/graph/snapshot.h"
+#include "services/gfx/compositor/graph/scene_content.h"
#include "services/gfx/compositor/render/render_image.h"
-#include "services/gfx/compositor/render/render_layer.h"
namespace compositor {
@@ -31,11 +29,8 @@ void ReleaseMailboxTexture(
}
} // namespace
-SceneDef::SceneDef(mojo::gfx::composition::SceneTokenPtr scene_token,
- const std::string& label)
- : scene_token_(scene_token.Pass()), label_(label) {
- DCHECK(scene_token_);
-}
+SceneDef::SceneDef(const SceneLabel& label)
+ : label_(label), weak_factory_(this) {}
SceneDef::~SceneDef() {}
@@ -68,15 +63,8 @@ SceneDef::Disposition SceneDef::Present(
end--;
}
- // Prepare to apply all publications up to this point.
- uint32_t version = pending_publications_[end - 1]->metadata->version;
- if (version_ != version) {
- version_ = version;
- formatted_label_cache_.clear();
- }
- Invalidate();
-
- // Apply all updates sequentially.
+ // Apply all updates sequentially up to this point.
+ version_ = pending_publications_[end - 1]->metadata->version;
for (size_t index = 0; index < end; ++index) {
for (auto& update : pending_publications_[index]->updates) {
if (!ApplyUpdate(update.Pass(), resolver, unavailable_sender, err))
@@ -88,10 +76,12 @@ SceneDef::Disposition SceneDef::Present(
pending_publications_.erase(pending_publications_.begin(),
pending_publications_.begin() + end);
- // Ensure the scene is in a valid state.
- if (!Validate(err))
- return Disposition::kFailed;
- return Disposition::kSucceeded;
+ // Rebuild the scene content, gathering all reachable nodes and resources
+ // and verifying that everything is correctly linked.
+ SceneContentBuilder builder(this, version_, err, resources_.size(),
+ nodes_.size());
+ content_ = builder.Build();
+ return content_ ? Disposition::kSucceeded : Disposition::kFailed;
}
bool SceneDef::ApplyUpdate(mojo::gfx::composition::SceneUpdatePtr update,
@@ -100,6 +90,12 @@ bool SceneDef::ApplyUpdate(mojo::gfx::composition::SceneUpdatePtr update,
std::ostream& err) {
DCHECK(update);
+ // TODO(jeffbrown): We may be able to reuse some content from previous
+ // versions even when the client removes and recreates resources or nodes.
+ // To reduce unnecessary churn, consider keeping track of items which have
+ // been removed or are being replaced then checking to see whether they
+ // really changed.
+
// Update resources.
if (update->clear_resources) {
resources_.clear();
@@ -109,11 +105,11 @@ bool SceneDef::ApplyUpdate(mojo::gfx::composition::SceneUpdatePtr update,
uint32_t resource_id = it.GetKey();
mojo::gfx::composition::ResourcePtr& resource_decl = it.GetValue();
if (resource_decl) {
- ResourceDef* resource = CreateResource(resource_id, resource_decl.Pass(),
- resolver, unavailable_sender, err);
+ scoped_refptr<const ResourceDef> resource = CreateResource(
+ resource_id, resource_decl.Pass(), resolver, unavailable_sender, err);
if (!resource)
return false;
- resources_[resource_id].reset(resource);
+ resources_[resource_id] = std::move(resource);
} else {
resources_.erase(resource_id);
}
@@ -127,10 +123,11 @@ bool SceneDef::ApplyUpdate(mojo::gfx::composition::SceneUpdatePtr update,
uint32_t node_id = it.GetKey();
mojo::gfx::composition::NodePtr& node_decl = it.GetValue();
if (node_decl) {
- NodeDef* node = CreateNode(node_id, node_decl.Pass(), err);
+ scoped_refptr<const NodeDef> node =
+ CreateNode(node_id, node_decl.Pass(), err);
if (!node)
return false;
- nodes_[node_id].reset(node);
+ nodes_[node_id] = std::move(node);
} else {
nodes_.erase(node_id);
}
@@ -138,22 +135,6 @@ bool SceneDef::ApplyUpdate(mojo::gfx::composition::SceneUpdatePtr update,
return true;
}
-bool SceneDef::Validate(std::ostream& err) {
- // Validate all nodes.
- // TODO(jeffbrown): Figure out how to do this incrementally if it gets
- // too expensive to process all nodes each time.
- root_node_ = nullptr;
- for (auto& pair : nodes_) {
- uint32_t node_id = pair.first;
- NodeDef* node = pair.second.get();
- if (!node->Validate(this, err))
- return false;
- if (node_id == mojo::gfx::composition::kSceneRootNodeId)
- root_node_ = node;
- }
- return true;
-}
-
bool SceneDef::UnlinkReferencedScene(
SceneDef* scene,
const SceneUnavailableSender& unavailable_sender) {
@@ -162,11 +143,11 @@ bool SceneDef::UnlinkReferencedScene(
bool changed = false;
for (auto& pair : resources_) {
if (pair.second->type() == ResourceDef::Type::kScene) {
- auto scene_resource = static_cast<SceneResourceDef*>(pair.second.get());
- if (scene_resource->referenced_scene() == scene) {
- scene_resource->clear_referenced_scene();
- Invalidate();
+ auto scene_resource =
+ static_cast<const SceneResourceDef*>(pair.second.get());
+ if (scene_resource->referenced_scene().get() == scene) {
changed = true;
+ pair.second = scene_resource->Unlink();
unavailable_sender.Run(pair.first);
}
}
@@ -174,86 +155,7 @@ bool SceneDef::UnlinkReferencedScene(
return changed;
}
-bool SceneDef::Snapshot(SnapshotBuilder* snapshot_builder,
- RenderLayerBuilder* layer_builder) {
- DCHECK(snapshot_builder);
- DCHECK(layer_builder);
-
- // Detect cycles.
- if (visited_) {
- if (snapshot_builder->block_log()) {
- *snapshot_builder->block_log()
- << "Scene blocked due to recursive cycle: " << FormattedLabel()
- << std::endl;
- }
- return false;
- }
-
- // Snapshot the contents of the scene.
- visited_ = true;
- bool success = SnapshotInner(snapshot_builder, layer_builder);
- visited_ = false;
- return success;
-}
-
-bool SceneDef::SnapshotInner(SnapshotBuilder* snapshot_builder,
- RenderLayerBuilder* layer_builder) {
- // Note the dependency even if blocked.
- snapshot_builder->AddSceneDependency(this);
-
- // Ensure we have a root node.
- if (!root_node_) {
- if (snapshot_builder->block_log()) {
- *snapshot_builder->block_log()
- << "Scene blocked due because it has no root node: "
- << FormattedLabel() << std::endl;
- }
- return false;
- }
-
- // Snapshot and draw the layer.
- std::shared_ptr<RenderLayer> scene_layer = SnapshotLayer(snapshot_builder);
- if (!scene_layer)
- return false;
- layer_builder->DrawLayer(scene_layer);
- return true;
-}
-
-std::shared_ptr<RenderLayer> SceneDef::SnapshotLayer(
- SnapshotBuilder* snapshot_builder) {
- if (cached_layer_)
- return cached_layer_;
-
- RenderLayerBuilder scene_layer_builder;
- scene_layer_builder.PushScene(scene_token_->value, version_);
- if (!root_node_->Snapshot(snapshot_builder, &scene_layer_builder, this))
- return nullptr;
- scene_layer_builder.PopScene();
-
- // TODO(jeffbrown): Implement caching even when the scene has dependencies.
- // There are some subtleties to be dealt with to ensure that caches
- // are properly invalidated and that we don't accidentally cache layers which
- // bake in decisions which counteract the intended cycle detection and
- // avoidance behavior. Basically just need better bookkeeping.
- std::shared_ptr<RenderLayer> scene_layer = scene_layer_builder.Build();
- if (!HasSceneResources())
- cached_layer_ = scene_layer;
- return scene_layer;
-}
-
-void SceneDef::Invalidate() {
- cached_layer_.reset();
-}
-
-bool SceneDef::HasSceneResources() {
- for (auto& pair : resources_) {
- if (pair.second->type() == ResourceDef::Type::kScene)
- return true;
- }
- return false;
-}
-
-ResourceDef* SceneDef::CreateResource(
+scoped_refptr<const ResourceDef> SceneDef::CreateResource(
uint32_t resource_id,
mojo::gfx::composition::ResourcePtr resource_decl,
const SceneResolver& resolver,
@@ -264,12 +166,13 @@ ResourceDef* SceneDef::CreateResource(
if (resource_decl->is_scene()) {
auto& scene_resource_decl = resource_decl->get_scene();
DCHECK(scene_resource_decl->scene_token);
- SceneDef* referenced_scene =
- resolver.Run(scene_resource_decl->scene_token.get());
- if (!referenced_scene) {
+
+ const mojo::gfx::composition::SceneToken& scene_token =
+ *scene_resource_decl->scene_token;
+ base::WeakPtr<SceneDef> referenced_scene = resolver.Run(scene_token);
+ if (!referenced_scene)
unavailable_sender.Run(resource_id);
- }
- return new SceneResourceDef(referenced_scene);
+ return new SceneResourceDef(scene_token, referenced_scene);
}
if (resource_decl->is_mailbox_texture()) {
@@ -277,8 +180,9 @@ ResourceDef* SceneDef::CreateResource(
DCHECK(mailbox_texture_resource_decl->mailbox_name.size() ==
GL_MAILBOX_SIZE_CHROMIUM);
DCHECK(mailbox_texture_resource_decl->size);
- int32_t width = mailbox_texture_resource_decl->size->width;
- int32_t height = mailbox_texture_resource_decl->size->height;
+
+ const int32_t width = mailbox_texture_resource_decl->size->width;
+ const int32_t height = mailbox_texture_resource_decl->size->height;
if (width < 1 || width > kMaxTextureWidth || height < 1 ||
height > kMaxTextureHeight) {
err << "MailboxTexture resource has invalid size: "
@@ -286,10 +190,12 @@ ResourceDef* SceneDef::CreateResource(
<< ", height=" << height;
return nullptr;
}
+ const GLbyte* const mailbox_name = reinterpret_cast<GLbyte*>(
+ mailbox_texture_resource_decl->mailbox_name.data());
+ const GLuint sync_point = mailbox_texture_resource_decl->sync_point;
+
std::shared_ptr<RenderImage> image = RenderImage::CreateFromMailboxTexture(
- reinterpret_cast<GLbyte*>(
- mailbox_texture_resource_decl->mailbox_name.data()),
- mailbox_texture_resource_decl->sync_point, width, height,
+ mailbox_name, sync_point, width, height,
base::MessageLoop::current()->task_runner(),
base::Bind(
&ReleaseMailboxTexture,
@@ -307,86 +213,97 @@ ResourceDef* SceneDef::CreateResource(
return nullptr;
}
-NodeDef* SceneDef::CreateNode(uint32_t node_id,
- mojo::gfx::composition::NodePtr node_decl,
- std::ostream& err) {
+scoped_refptr<const NodeDef> SceneDef::CreateNode(
+ uint32_t node_id,
+ mojo::gfx::composition::NodePtr node_decl,
+ std::ostream& err) {
DCHECK(node_decl);
- NodeOp* op = nullptr;
- if (node_decl->op) {
- op = CreateNodeOp(node_id, node_decl->op.Pass(), err);
- if (!op)
- return nullptr;
+ mojo::TransformPtr content_transform = node_decl->content_transform.Pass();
+ mojo::RectPtr content_clip = node_decl->content_clip.Pass();
+ const mojo::gfx::composition::Node::Combinator combinator =
+ node_decl->combinator;
+ const std::vector<uint32_t>& child_node_ids =
+ node_decl->child_node_ids.storage();
+
+ if (!node_decl->op) {
+ return new NodeDef(node_id, content_transform.Pass(), content_clip.Pass(),
+ combinator, child_node_ids);
}
- return new NodeDef(node_id, node_decl->content_transform.Pass(),
- node_decl->content_clip.Pass(), node_decl->hit_id,
- node_decl->combinator, node_decl->child_node_ids.storage(),
- op);
-}
+ if (node_decl->op->is_rect()) {
+ auto& rect_node_decl = node_decl->op->get_rect();
+ DCHECK(rect_node_decl->content_rect);
+ DCHECK(rect_node_decl->color);
-NodeOp* SceneDef::CreateNodeOp(uint32_t node_id,
- mojo::gfx::composition::NodeOpPtr node_op_decl,
- std::ostream& err) {
- DCHECK(node_op_decl);
-
- if (node_op_decl->is_rect()) {
- auto& rect_node_op_decl = node_op_decl->get_rect();
- DCHECK(rect_node_op_decl->content_rect);
- DCHECK(rect_node_op_decl->color);
- return new RectNodeOp(*rect_node_op_decl->content_rect,
- *rect_node_op_decl->color);
+ const mojo::Rect& content_rect = *rect_node_decl->content_rect;
+ const mojo::gfx::composition::Color& color = *rect_node_decl->color;
+ return new RectNodeDef(node_id, content_transform.Pass(),
+ content_clip.Pass(), combinator, child_node_ids,
+ content_rect, color);
}
- if (node_op_decl->is_image()) {
- auto& image_node_op_decl = node_op_decl->get_image();
- DCHECK(image_node_op_decl->content_rect);
- return new ImageNodeOp(*image_node_op_decl->content_rect,
- image_node_op_decl->image_rect.Pass(),
- image_node_op_decl->image_resource_id,
- image_node_op_decl->blend.Pass());
+ if (node_decl->op->is_image()) {
+ auto& image_node_decl = node_decl->op->get_image();
+ DCHECK(image_node_decl->content_rect);
+
+ const mojo::Rect& content_rect = *image_node_decl->content_rect;
+ mojo::RectPtr image_rect = image_node_decl->image_rect.Pass();
+ const uint32 image_resource_id = image_node_decl->image_resource_id;
+ mojo::gfx::composition::BlendPtr blend = image_node_decl->blend.Pass();
+ return new ImageNodeDef(node_id, content_transform.Pass(),
+ content_clip.Pass(), combinator, child_node_ids,
+ content_rect, image_rect.Pass(), image_resource_id,
+ blend.Pass());
}
- if (node_op_decl->is_scene()) {
- auto& scene_node_op_decl = node_op_decl->get_scene();
- return new SceneNodeOp(scene_node_op_decl->scene_resource_id,
- scene_node_op_decl->scene_version);
+ if (node_decl->op->is_scene()) {
+ auto& scene_node_decl = node_decl->op->get_scene();
+
+ const uint32_t scene_resource_id = scene_node_decl->scene_resource_id;
+ const uint32_t scene_version = scene_node_decl->scene_version;
+ return new SceneNodeDef(node_id, content_transform.Pass(),
+ content_clip.Pass(), combinator, child_node_ids,
+ scene_resource_id, scene_version);
}
- if (node_op_decl->is_layer()) {
- auto& layer_node_op_decl = node_op_decl->get_layer();
- DCHECK(layer_node_op_decl->layer_size);
- return new LayerNodeOp(*layer_node_op_decl->layer_size,
- layer_node_op_decl->blend.Pass());
+ if (node_decl->op->is_layer()) {
+ auto& layer_node_decl = node_decl->op->get_layer();
+ DCHECK(layer_node_decl->layer_size);
+
+ const mojo::Size& layer_size = *layer_node_decl->layer_size;
+ mojo::gfx::composition::BlendPtr blend = layer_node_decl->blend.Pass();
+ return new LayerNodeDef(node_id, content_transform.Pass(),
+ content_clip.Pass(), combinator, child_node_ids,
+ layer_size, blend.Pass());
}
err << "Unsupported node op type: node_id=" << node_id
- << ", node_op=" << node_op_decl;
+ << ", node_op=" << node_decl->op;
return nullptr;
}
-NodeDef* SceneDef::FindNode(uint32_t node_id) {
+const NodeDef* SceneDef::FindNode(uint32_t node_id) const {
auto it = nodes_.find(node_id);
return it != nodes_.end() ? it->second.get() : nullptr;
}
-ResourceDef* SceneDef::FindResource(uint32_t resource_id,
- ResourceDef::Type resource_type) {
+const ResourceDef* SceneDef::FindResource(uint32_t resource_id) const {
auto it = resources_.find(resource_id);
- return it != resources_.end() && it->second->type() == resource_type
- ? it->second.get()
- : nullptr;
+ return it != resources_.end() ? it->second.get() : nullptr;
}
-std::string SceneDef::FormattedLabel() {
- if (formatted_label_cache_.empty()) {
- formatted_label_cache_ =
- label_.empty()
- ? base::StringPrintf("<%d/%d>", scene_token_->value, version_)
- : base::StringPrintf("<%d:%s/%d>", scene_token_->value,
- label_.c_str(), version_);
- }
- return formatted_label_cache_;
+const SceneContent* SceneDef::FindContent(uint32_t version) const {
+ if (!content_)
+ return nullptr;
+
+ // TODO(jeffbrown): Consider briefly caching older versions to allow them
+ // to be used to provide alternate content for node combinators.
+ if (version != mojo::gfx::composition::kSceneVersionNone &&
+ version != content_->version() &&
+ content_->version() != mojo::gfx::composition::kSceneVersionNone)
+ return nullptr;
+ return content_.get();
}
SceneDef::Publication::Publication(
« no previous file with comments | « services/gfx/compositor/graph/scene_def.h ('k') | services/gfx/compositor/graph/scene_label.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698