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

Unified 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: 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/snapshot.h ('k') | services/gfx/compositor/render/render_frame.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: services/gfx/compositor/graph/snapshot.cc
diff --git a/services/gfx/compositor/graph/snapshot.cc b/services/gfx/compositor/graph/snapshot.cc
index 935fa2055b790c2a5b402736cb9be84e08e02344..ab4a4478ed2d2302cc30cce06bdf70ab306621fb 100644
--- a/services/gfx/compositor/graph/snapshot.cc
+++ b/services/gfx/compositor/graph/snapshot.cc
@@ -5,9 +5,10 @@
#include "services/gfx/compositor/graph/snapshot.h"
#include "base/logging.h"
+#include "services/gfx/compositor/graph/scene_content.h"
#include "services/gfx/compositor/graph/scene_def.h"
#include "services/gfx/compositor/render/render_frame.h"
-#include "services/gfx/compositor/render/render_layer.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkRect.h"
namespace compositor {
@@ -20,19 +21,42 @@ bool Snapshot::Invalidate() {
if (valid_) {
valid_ = false;
dependencies_.clear();
- frame_.reset();
+ ClearContent();
return true;
}
return false;
}
-bool Snapshot::InvalidateScene(SceneDef* scene_def) {
+bool Snapshot::InvalidateScene(const SceneDef* scene_def) {
DCHECK(scene_def);
+ return valid_ &&
+ dependencies_.find(scene_def->label().token()) !=
+ dependencies_.end() &&
+ Invalidate();
+}
- if (valid_ && dependencies_.find(scene_def) != dependencies_.end()) {
- return Invalidate();
- }
- return false;
+void Snapshot::ClearContent() {
+ root_scene_content_ = nullptr;
+ resolved_scene_contents_.clear();
+ node_dispositions_.clear();
+ frame_.reset();
+}
+
+bool Snapshot::IsBlocked(const NodeDef* node) const {
+ DCHECK(valid_);
+ auto it = node_dispositions_.find(node);
+ DCHECK(it != node_dispositions_.end());
+ DCHECK(it->second == Disposition::kSuccess ||
+ it->second == Disposition::kBlocked);
+ return it->second == Disposition::kBlocked;
+}
+
+const SceneContent* Snapshot::GetResolvedSceneContent(
+ const SceneNodeDef* scene_node) const {
+ DCHECK(valid_);
+ auto it = resolved_scene_contents_.find(scene_node);
+ DCHECK(it != resolved_scene_contents_.end());
+ return it->second.get();
}
SnapshotBuilder::SnapshotBuilder(std::ostream* block_log)
@@ -40,26 +64,164 @@ SnapshotBuilder::SnapshotBuilder(std::ostream* block_log)
SnapshotBuilder::~SnapshotBuilder() {}
-void SnapshotBuilder::AddSceneDependency(SceneDef* scene) {
+Snapshot::Disposition SnapshotBuilder::SnapshotNode(
+ const NodeDef* node,
+ const SceneContent* content) {
+ DCHECK(snapshot_);
+ DCHECK(node);
+ DCHECK(content);
+ DCHECK(node != content->GetRootNodeIfExists());
+
+ auto it = snapshot_->node_dispositions_.find(node);
+ if (it != snapshot_->node_dispositions_.end())
+ return it->second;
+
+ Snapshot::Disposition disposition = node->RecordSnapshot(content, this);
+ snapshot_->node_dispositions_[node] = disposition;
+ return disposition;
+}
+
+Snapshot::Disposition SnapshotBuilder::SnapshotRootAndDetectCycles(
+ const NodeDef* node,
+ const SceneContent* content) {
DCHECK(snapshot_);
- snapshot_->dependencies_.insert(scene);
+ DCHECK(node);
+ DCHECK(content);
+ DCHECK(node == content->GetRootNodeIfExists());
+
+ auto storage = snapshot_->node_dispositions_.emplace(
+ node, Snapshot::Disposition::kCycle);
+ if (!storage.second) {
+ if (storage.first->second == Snapshot::Disposition::kCycle)
+ cycle_ = content; // start unwinding, remember where to stop
+ return storage.first->second;
+ }
+
+ Snapshot::Disposition disposition = node->RecordSnapshot(content, this);
+ if (disposition == Snapshot::Disposition::kSuccess) {
+ snapshot_->node_dispositions_[node] = disposition;
+ return disposition;
+ }
+
+ // We cannot reuse the iterator in |storage.first| because it may have
+ // been invalidated by the call to |RecordSnapshot| due to rehashing so
+ // we must look up the node again just in case.
+ snapshot_->node_dispositions_[node] = Snapshot::Disposition::kBlocked;
+
+ if (disposition == Snapshot::Disposition::kCycle) {
+ DCHECK(cycle_);
+ if (block_log_) {
+ *block_log_ << "Scene blocked because it is part of a cycle: "
+ << content->FormattedLabel() << std::endl;
+ }
+ if (cycle_ == content) {
+ cycle_ = nullptr; // found the ouroboros tail, stop unwinding
+ disposition = Snapshot::Disposition::kBlocked;
+ }
+ }
+ return disposition;
+}
+Snapshot::Disposition SnapshotBuilder::SnapshotScene(
+ const SceneDef* scene,
+ uint32_t version,
+ const SceneNodeDef* referrer_node,
+ const SceneContent* referrer_content) {
+ DCHECK(snapshot_);
+ DCHECK(scene);
+ DCHECK(referrer_node);
+ DCHECK(referrer_content);
+
+ // This function should only ever be called once when snapshotting the
+ // referring |SceneNodeDef| at which point the result will be memoized
+ // by |SnapshotNode| as usual so reentrance should not occur.
+ DCHECK(snapshot_->resolved_scene_contents_.find(referrer_node) ==
+ snapshot_->resolved_scene_contents_.end());
+
+ snapshot_->dependencies_.insert(scene->label().token());
+
+ const SceneContent* content = scene->FindContent(version);
+ if (!content) {
+ if (block_log_) {
+ *block_log_ << "Scene node blocked because its referenced scene is not "
+ "available with the requested version: "
+ << referrer_node->FormattedLabel(referrer_content)
+ << ", scene " << scene->label().FormattedLabel()
+ << ", requested version " << version << ", current version "
+ << scene->version() << std::endl;
+ }
+ return Snapshot::Disposition::kBlocked;
+ }
+
+ const NodeDef* root = content->GetRootNodeIfExists();
+ if (!root) {
+ if (block_log_) {
+ *block_log_ << "Scene node blocked because its referenced scene has no "
+ "root node: "
+ << referrer_node->FormattedLabel(referrer_content)
+ << ", scene " << content->FormattedLabel() << std::endl;
+ }
+ return Snapshot::Disposition::kBlocked;
+ }
+
+ snapshot_->resolved_scene_contents_[referrer_node] = content;
+ return SnapshotRootAndDetectCycles(root, content);
+}
+
+Snapshot::Disposition SnapshotBuilder::SnapshotRenderer(const SceneDef* scene) {
+ DCHECK(!snapshot_->root_scene_content_);
+
+ snapshot_->dependencies_.insert(scene->label().token());
+
+ const SceneContent* content =
+ scene->FindContent(mojo::gfx::composition::kSceneVersionNone);
+ if (!content) {
+ if (block_log_) {
+ *block_log_ << "Rendering blocked because the root scene has no content: "
+ << scene->label().FormattedLabel() << std::endl;
+ }
+ return Snapshot::Disposition::kBlocked;
+ }
+
+ const NodeDef* root = content->GetRootNodeIfExists();
+ if (!root) {
+ if (block_log_) {
+ *block_log_ << "Rendering blocked the root scene has no root node: "
+ << content->FormattedLabel() << std::endl;
+ }
+ return Snapshot::Disposition::kBlocked;
+ }
+
+ snapshot_->root_scene_content_ = content;
+ return SnapshotRootAndDetectCycles(root, content);
}
std::unique_ptr<Snapshot> SnapshotBuilder::Build(
- SceneDef* root_scene,
+ const SceneDef* root_scene,
const mojo::Rect& viewport,
const mojo::gfx::composition::FrameInfo& frame_info) {
DCHECK(snapshot_);
DCHECK(root_scene);
- SkRect sk_viewport =
- SkRect::MakeXYWH(viewport.x, viewport.y, viewport.width, viewport.height);
- RenderLayerBuilder layer_builder(&sk_viewport);
- if (root_scene->Snapshot(this, &layer_builder)) {
+ Snapshot::Disposition disposition = SnapshotRenderer(root_scene);
+ DCHECK(!cycle_); // must have properly unwound any cycles by now
+
+ if (disposition == Snapshot::Disposition::kSuccess) {
+ SkRect sk_viewport = SkRect::MakeXYWH(viewport.x, viewport.y,
+ viewport.width, viewport.height);
+ SkPictureRecorder recorder;
+ recorder.beginRecording(sk_viewport);
+
+ const NodeDef* root_node =
+ snapshot_->root_scene_content_->GetRootNodeIfExists();
+ DCHECK(root_node); // otherwise would have failed to snapshot
+ root_node->RecordPicture(snapshot_->root_scene_content_.get(),
+ snapshot_.get(), recorder.getRecordingCanvas());
+
snapshot_->frame_ =
- RenderFrame::Create(layer_builder.Build(), sk_viewport, frame_info);
+ RenderFrame::Create(skia::AdoptRef(recorder.endRecordingAsPicture()),
+ sk_viewport, frame_info);
} else {
- snapshot_->valid_ = false;
+ snapshot_->ClearContent();
}
return std::move(snapshot_);
}
« no previous file with comments | « services/gfx/compositor/graph/snapshot.h ('k') | services/gfx/compositor/render/render_frame.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698