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

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

Issue 1552963002: Initial checkin of the new Mozart compositor. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-11
Patch Set: Created 4 years, 12 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
Index: services/gfx/compositor/graph/node_def.cc
diff --git a/services/gfx/compositor/graph/node_def.cc b/services/gfx/compositor/graph/node_def.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7f731b95ad3b80bad8a1fecc2da466324c3326bc
--- /dev/null
+++ b/services/gfx/compositor/graph/node_def.cc
@@ -0,0 +1,366 @@
+// Copyright 2015 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/node_def.h"
+
+#include <sstream>
+
+#include "base/logging.h"
+#include "mojo/services/gfx/composition/cpp/logging.h"
+#include "services/gfx/compositor/graph/scene_def.h"
+#include "services/gfx/compositor/graph/snapshot.h"
+#include "services/gfx/compositor/render/render_image.h"
+#include "services/gfx/compositor/render/render_layer.h"
+
+namespace compositor {
+
+// TODO(jeffbrown): Move these conversion functions somewhere more useful.
abarth 2016/01/10 22:55:36 There's a converters directory in mojo/common. Ma
jeffbrown 2016/01/16 03:28:32 Yeah... but maybe later. :)
+
+static SkRect ToSkRect(const mojo::Rect& rect) {
abarth 2016/01/10 22:55:36 The mojo types have template magic to make these s
+ return SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height);
+}
+
+static SkRRect ToSkRRect(const mojo::RRect& rrect) {
+ SkVector radii[4] = {
+ {rrect.top_left_radius_x, rrect.top_left_radius_y},
+ {rrect.top_right_radius_x, rrect.top_right_radius_y},
+ {rrect.bottom_left_radius_x, rrect.bottom_left_radius_y},
+ {rrect.bottom_right_radius_x, rrect.bottom_right_radius_y}};
+ SkRRect result;
+ result.setRectRadii(
+ SkRect::MakeXYWH(rrect.x, rrect.y, rrect.width, rrect.height), radii);
abarth 2016/01/10 22:55:35 Note that this routine is more expensive that setR
jeffbrown 2016/01/16 03:28:32 Yes, but we don't know whether we're in the fast c
+ return result;
+}
+
+static SkMatrix ToSkMatrix(const mojo::Transform& transform) {
+ // TODO(jeffbrown): What to do with the Z components?
+ // Perhaps we need a simpler 2D transform matrix mojom.
abarth 2016/01/10 22:55:36 This is the same thing we do in Flutter. We can t
jeffbrown 2016/01/16 03:28:32 Acknowledged.
+ SkMatrix result;
+ result.setAll(transform.matrix[0], transform.matrix[1], transform.matrix[3],
+ transform.matrix[4], transform.matrix[5], transform.matrix[7],
+ transform.matrix[12], transform.matrix[13],
+ transform.matrix[15]);
+ return result;
+}
+
+static SkColor ToSkColor(const mojo::gfx::composition::Color& color) {
+ return SkColorSetARGBInline(color.alpha, color.red, color.green, color.blue);
+}
+
+static SkPath ToSkPath(const mojo::gfx::composition::Clip& clip) {
+ SkPath result;
+ if (clip.is_rect()) {
+ result.addRect(ToSkRect(*clip.get_rect()));
abarth 2016/01/10 22:55:36 Woah there. I haven't seen where you're using thi
jeffbrown 2016/01/16 03:28:32 Dropping RRect clips for now.
+ } else if (clip.is_rect()) {
+ result.addRRect(ToSkRRect(*clip.get_rrect()));
+ } else {
+ DCHECK(false); // was checked during validation
+ }
+ return result;
+}
+
+static SkPaint ToSkPaint(const mojo::gfx::composition::Blend& blend) {
+ SkPaint result;
+ result.setAlpha(blend.alpha);
+ return result;
+}
+
+NodeDef::NodeDef(uint32_t node_id,
+ mojo::TransformPtr content_transform,
+ mojo::gfx::composition::ClipPtr content_clip,
+ uint32_t hit_id,
+ Combinator combinator,
+ const std::vector<uint32_t>& child_node_ids,
+ NodeOp* op)
+ : node_id_(node_id),
+ content_transform_(content_transform.Pass()),
+ content_clip_(content_clip.Pass()),
+ hit_id_(hit_id),
+ combinator_(combinator),
+ child_node_ids_(child_node_ids),
+ op_(op) {}
+
+NodeDef::~NodeDef() {}
+
+bool NodeDef::Validate(SceneDef* scene, std::ostream& err) {
+ if (content_clip_) {
+ if (!content_clip_->is_rect() && !content_clip_->is_rrect()) {
+ err << "Node contains unsupported content clip type: "
+ << FormattedLabel(scene);
+ return false;
+ }
+ }
+
+ child_nodes_.clear();
+ for (uint32_t child_node_id : child_node_ids_) {
+ NodeDef* child_node = scene->FindNode(child_node_id);
+ if (!child_node) {
+ err << "Node refers to unknown child: " << FormattedLabel(scene)
+ << ", child_node_id=" << child_node_id;
+ return false;
+ }
+ child_nodes_.push_back(child_node);
+ }
+
+ return !op_ || op_->Validate(scene, this, err);
+}
+
+bool NodeDef::Snapshot(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene) {
+ DCHECK(snapshot_builder);
+ DCHECK(layer_builder);
+ DCHECK(scene);
+
+ // Detect cycles.
+ if (visited_) {
+ if (snapshot_builder->block_log()) {
+ *snapshot_builder->block_log()
+ << "Node blocked due to recursive cycle: " << FormattedLabel(scene)
+ << std::endl;
+ }
+ return false;
+ }
+
+ // Snapshot the contents of the node.
+ visited_ = true;
+ bool success = SnapshotInner(snapshot_builder, layer_builder, scene);
+ visited_ = false;
+ return success;
+}
+
+bool NodeDef::SnapshotInner(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene) {
+ // TODO(jeffbrown): Frequently referenced and reused nodes, especially
+ // layer nodes, may benefit from caching.
+ layer_builder->PushNode(
+ node_id_, hit_id_,
+ content_transform_ ? ToSkMatrix(*content_transform_) : SkMatrix::I(),
+ content_clip_ ? ToSkPath(*content_clip_) : SkPath());
+
+ bool success =
+ op_ ? op_->Snapshot(snapshot_builder, layer_builder, scene, this)
+ : SnapshotChildren(snapshot_builder, layer_builder, scene);
+ if (!success)
+ return false;
+
+ layer_builder->PopNode();
+ return true;
+}
+
+bool NodeDef::SnapshotChildren(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene) {
+ DCHECK(snapshot_builder);
+ DCHECK(layer_builder);
+ DCHECK(scene);
+
+ switch (combinator_) {
+ // MERGE: All or nothing.
+ case Combinator::MERGE: {
+ for (NodeDef* child_node : child_nodes_) {
+ if (!child_node->Snapshot(snapshot_builder, layer_builder, scene)) {
+ if (snapshot_builder->block_log()) {
+ *snapshot_builder->block_log()
+ << "Node with MERGE combinator blocked since "
+ "one of its children is blocked: "
+ << FormattedLabel(scene) << ", blocked child "
+ << child_node->FormattedLabel(scene) << std::endl;
+ }
+ return false; // blocked
+ }
+ }
+ return true;
+ }
+
+ // PRUNE: Silently discard blocked children.
+ case Combinator::PRUNE: {
+ for (NodeDef* child_node : child_nodes_) {
+ RenderLayerBuilder child_layer_builder;
+ if (child_node->Snapshot(snapshot_builder, &child_layer_builder,
+ scene)) {
+ layer_builder->DrawLayer(child_layer_builder.Build());
+ }
+ }
+ return true;
+ }
+
+ // FALLBACK: Keep only the first unblocked child.
+ case Combinator::FALLBACK: {
+ if (child_nodes_.empty())
+ return true;
+ for (NodeDef* child_node : child_nodes_) {
+ RenderLayerBuilder child_layer_builder;
+ if (child_node->Snapshot(snapshot_builder, &child_layer_builder,
+ scene)) {
+ layer_builder->DrawLayer(child_layer_builder.Build());
+ return true;
+ }
+ }
+ if (snapshot_builder->block_log()) {
+ *snapshot_builder->block_log()
+ << "Node with FALLBACK combinator blocked since "
+ "all of its children are blocked: "
+ << FormattedLabel(scene) << std::endl;
+ }
+ return false; // blocked
+ }
+ }
+}
+
+std::string NodeDef::FormattedLabel(SceneDef* scene) {
+ std::ostringstream s;
+ s << scene->FormattedLabel() << "[" << node_id_ << "]";
+ return s.str();
abarth 2016/01/10 22:55:35 base::StringPrintf
jeffbrown 2016/01/16 03:28:32 Done.
+}
+
+bool NodeOp::Validate(SceneDef* scene, NodeDef* node, std::ostream& err) {
+ return true;
+}
+
+RectNodeOp::RectNodeOp(const mojo::Rect& content_rect,
+ const mojo::gfx::composition::Color& color)
+ : content_rect_(content_rect), color_(color) {}
+
+RectNodeOp::~RectNodeOp() {}
+
+bool RectNodeOp::Snapshot(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene,
+ NodeDef* node) {
+ if (!node->SnapshotChildren(snapshot_builder, layer_builder, scene))
+ return false;
+
+ SkPaint paint;
+ paint.setColor(ToSkColor(color_));
+ layer_builder->DrawRect(ToSkRect(content_rect_), paint);
+ return true;
+}
+
+ImageNodeOp::ImageNodeOp(const mojo::Rect& content_rect,
+ mojo::RectPtr image_rect,
+ uint32 image_resource_id,
+ mojo::gfx::composition::BlendPtr blend)
+ : content_rect_(content_rect),
+ image_rect_(image_rect.Pass()),
+ image_resource_id_(image_resource_id),
+ blend_(blend.Pass()) {}
+
+ImageNodeOp::~ImageNodeOp() {}
+
+bool ImageNodeOp::Validate(SceneDef* scene, NodeDef* node, std::ostream& err) {
+ image_resource_ = scene->FindImageResource(image_resource_id_);
+ if (!image_resource_) {
+ err << "Node refers to unknown or invalid image resource: "
+ << node->FormattedLabel(scene)
+ << ", image_resource_id=" << image_resource_id_;
+ return false;
+ }
+ return true;
+}
+
+bool ImageNodeOp::Snapshot(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene,
+ NodeDef* node) {
+ DCHECK(image_resource_);
+
+ if (!image_resource_->image()) {
+ if (snapshot_builder->block_log()) {
+ *snapshot_builder->block_log()
+ << "Node blocked due to its referenced image "
+ "resource being unavailable: "
+ << node->FormattedLabel(scene) << std::endl;
+ }
+ return false;
+ }
+
+ if (!node->SnapshotChildren(snapshot_builder, layer_builder, scene))
+ return false;
+
+ layer_builder->DrawImage(
+ image_resource_->image(), ToSkRect(content_rect_),
+ image_rect_ ? ToSkRect(*image_rect_)
+ : SkRect::MakeWH(image_resource_->image()->width(),
+ image_resource_->image()->height()),
+ blend_ ? ToSkPaint(*blend_) : SkPaint());
+ return true;
+}
+
+SceneNodeOp::SceneNodeOp(uint32_t scene_resource_id, uint32_t scene_version)
+ : scene_resource_id_(scene_resource_id), scene_version_(scene_version) {}
+
+SceneNodeOp::~SceneNodeOp() {}
+
+bool SceneNodeOp::Validate(SceneDef* scene, NodeDef* node, std::ostream& err) {
+ scene_resource_ = scene->FindSceneResource(scene_resource_id_);
+ if (!scene_resource_) {
+ err << "Node refers to unknown or invalid scene resource: "
+ << node->FormattedLabel(scene)
+ << ", scene_resource_id=" << scene_resource_id_;
+ return false;
+ }
+ return true;
+}
+
+bool SceneNodeOp::Snapshot(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene,
+ NodeDef* node) {
+ DCHECK(scene_resource_);
+
+ SceneDef* referenced_scene = scene_resource_->referenced_scene();
+ if (!referenced_scene) {
+ if (snapshot_builder->block_log()) {
+ *snapshot_builder->block_log()
+ << "Node blocked due to its referenced scene "
+ "resource being unavailable: "
+ << node->FormattedLabel(scene) << std::endl;
+ }
+ return false;
+ }
+
+ uint32_t actual_version = referenced_scene->version();
+ if (scene_version_ != mojo::gfx::composition::kSceneVersionNone &&
+ actual_version != mojo::gfx::composition::kSceneVersionNone &&
+ scene_version_ != actual_version) {
+ if (snapshot_builder->block_log()) {
+ *snapshot_builder->block_log()
+ << "Node blocked due to its referenced scene "
+ "resource not having the desired version: "
+ << node->FormattedLabel(scene)
+ << ", requested_version=" << scene_version_
+ << ", actual_version=" << actual_version << std::endl;
+ }
+ return false;
+ }
+
+ if (!node->SnapshotChildren(snapshot_builder, layer_builder, scene))
+ return false;
+
+ return referenced_scene->Snapshot(snapshot_builder, layer_builder);
+}
+
+LayerNodeOp::LayerNodeOp(const mojo::Size& size,
+ mojo::gfx::composition::BlendPtr blend)
+ : size_(size), blend_(blend.Pass()) {}
+
+LayerNodeOp::~LayerNodeOp() {}
+
+bool LayerNodeOp::Snapshot(SnapshotBuilder* snapshot_builder,
+ RenderLayerBuilder* layer_builder,
+ SceneDef* scene,
+ NodeDef* node) {
+ SkRect content_rect = SkRect::MakeWH(size_.width, size_.height);
+ RenderLayerBuilder children_layer_builder(&content_rect);
+ if (!node->SnapshotChildren(snapshot_builder, &children_layer_builder, scene))
+ return false;
+
+ layer_builder->DrawSavedLayer(children_layer_builder.Build(), content_rect,
+ blend_ ? ToSkPaint(*blend_) : SkPaint());
+ return true;
+}
+
+} // namespace compositor

Powered by Google App Engine
This is Rietveld 408576698