Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "services/gfx/compositor/graph/node_def.h" | |
| 6 | |
| 7 #include <sstream> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "mojo/services/gfx/composition/cpp/logging.h" | |
| 11 #include "services/gfx/compositor/graph/scene_def.h" | |
| 12 #include "services/gfx/compositor/graph/snapshot.h" | |
| 13 #include "services/gfx/compositor/render/render_image.h" | |
| 14 #include "services/gfx/compositor/render/render_layer.h" | |
| 15 | |
| 16 namespace compositor { | |
| 17 | |
| 18 // 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. :)
| |
| 19 | |
| 20 static SkRect ToSkRect(const mojo::Rect& rect) { | |
|
abarth
2016/01/10 22:55:36
The mojo types have template magic to make these s
| |
| 21 return SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height); | |
| 22 } | |
| 23 | |
| 24 static SkRRect ToSkRRect(const mojo::RRect& rrect) { | |
| 25 SkVector radii[4] = { | |
| 26 {rrect.top_left_radius_x, rrect.top_left_radius_y}, | |
| 27 {rrect.top_right_radius_x, rrect.top_right_radius_y}, | |
| 28 {rrect.bottom_left_radius_x, rrect.bottom_left_radius_y}, | |
| 29 {rrect.bottom_right_radius_x, rrect.bottom_right_radius_y}}; | |
| 30 SkRRect result; | |
| 31 result.setRectRadii( | |
| 32 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
| |
| 33 return result; | |
| 34 } | |
| 35 | |
| 36 static SkMatrix ToSkMatrix(const mojo::Transform& transform) { | |
| 37 // TODO(jeffbrown): What to do with the Z components? | |
| 38 // 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.
| |
| 39 SkMatrix result; | |
| 40 result.setAll(transform.matrix[0], transform.matrix[1], transform.matrix[3], | |
| 41 transform.matrix[4], transform.matrix[5], transform.matrix[7], | |
| 42 transform.matrix[12], transform.matrix[13], | |
| 43 transform.matrix[15]); | |
| 44 return result; | |
| 45 } | |
| 46 | |
| 47 static SkColor ToSkColor(const mojo::gfx::composition::Color& color) { | |
| 48 return SkColorSetARGBInline(color.alpha, color.red, color.green, color.blue); | |
| 49 } | |
| 50 | |
| 51 static SkPath ToSkPath(const mojo::gfx::composition::Clip& clip) { | |
| 52 SkPath result; | |
| 53 if (clip.is_rect()) { | |
| 54 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.
| |
| 55 } else if (clip.is_rect()) { | |
| 56 result.addRRect(ToSkRRect(*clip.get_rrect())); | |
| 57 } else { | |
| 58 DCHECK(false); // was checked during validation | |
| 59 } | |
| 60 return result; | |
| 61 } | |
| 62 | |
| 63 static SkPaint ToSkPaint(const mojo::gfx::composition::Blend& blend) { | |
| 64 SkPaint result; | |
| 65 result.setAlpha(blend.alpha); | |
| 66 return result; | |
| 67 } | |
| 68 | |
| 69 NodeDef::NodeDef(uint32_t node_id, | |
| 70 mojo::TransformPtr content_transform, | |
| 71 mojo::gfx::composition::ClipPtr content_clip, | |
| 72 uint32_t hit_id, | |
| 73 Combinator combinator, | |
| 74 const std::vector<uint32_t>& child_node_ids, | |
| 75 NodeOp* op) | |
| 76 : node_id_(node_id), | |
| 77 content_transform_(content_transform.Pass()), | |
| 78 content_clip_(content_clip.Pass()), | |
| 79 hit_id_(hit_id), | |
| 80 combinator_(combinator), | |
| 81 child_node_ids_(child_node_ids), | |
| 82 op_(op) {} | |
| 83 | |
| 84 NodeDef::~NodeDef() {} | |
| 85 | |
| 86 bool NodeDef::Validate(SceneDef* scene, std::ostream& err) { | |
| 87 if (content_clip_) { | |
| 88 if (!content_clip_->is_rect() && !content_clip_->is_rrect()) { | |
| 89 err << "Node contains unsupported content clip type: " | |
| 90 << FormattedLabel(scene); | |
| 91 return false; | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 child_nodes_.clear(); | |
| 96 for (uint32_t child_node_id : child_node_ids_) { | |
| 97 NodeDef* child_node = scene->FindNode(child_node_id); | |
| 98 if (!child_node) { | |
| 99 err << "Node refers to unknown child: " << FormattedLabel(scene) | |
| 100 << ", child_node_id=" << child_node_id; | |
| 101 return false; | |
| 102 } | |
| 103 child_nodes_.push_back(child_node); | |
| 104 } | |
| 105 | |
| 106 return !op_ || op_->Validate(scene, this, err); | |
| 107 } | |
| 108 | |
| 109 bool NodeDef::Snapshot(SnapshotBuilder* snapshot_builder, | |
| 110 RenderLayerBuilder* layer_builder, | |
| 111 SceneDef* scene) { | |
| 112 DCHECK(snapshot_builder); | |
| 113 DCHECK(layer_builder); | |
| 114 DCHECK(scene); | |
| 115 | |
| 116 // Detect cycles. | |
| 117 if (visited_) { | |
| 118 if (snapshot_builder->block_log()) { | |
| 119 *snapshot_builder->block_log() | |
| 120 << "Node blocked due to recursive cycle: " << FormattedLabel(scene) | |
| 121 << std::endl; | |
| 122 } | |
| 123 return false; | |
| 124 } | |
| 125 | |
| 126 // Snapshot the contents of the node. | |
| 127 visited_ = true; | |
| 128 bool success = SnapshotInner(snapshot_builder, layer_builder, scene); | |
| 129 visited_ = false; | |
| 130 return success; | |
| 131 } | |
| 132 | |
| 133 bool NodeDef::SnapshotInner(SnapshotBuilder* snapshot_builder, | |
| 134 RenderLayerBuilder* layer_builder, | |
| 135 SceneDef* scene) { | |
| 136 // TODO(jeffbrown): Frequently referenced and reused nodes, especially | |
| 137 // layer nodes, may benefit from caching. | |
| 138 layer_builder->PushNode( | |
| 139 node_id_, hit_id_, | |
| 140 content_transform_ ? ToSkMatrix(*content_transform_) : SkMatrix::I(), | |
| 141 content_clip_ ? ToSkPath(*content_clip_) : SkPath()); | |
| 142 | |
| 143 bool success = | |
| 144 op_ ? op_->Snapshot(snapshot_builder, layer_builder, scene, this) | |
| 145 : SnapshotChildren(snapshot_builder, layer_builder, scene); | |
| 146 if (!success) | |
| 147 return false; | |
| 148 | |
| 149 layer_builder->PopNode(); | |
| 150 return true; | |
| 151 } | |
| 152 | |
| 153 bool NodeDef::SnapshotChildren(SnapshotBuilder* snapshot_builder, | |
| 154 RenderLayerBuilder* layer_builder, | |
| 155 SceneDef* scene) { | |
| 156 DCHECK(snapshot_builder); | |
| 157 DCHECK(layer_builder); | |
| 158 DCHECK(scene); | |
| 159 | |
| 160 switch (combinator_) { | |
| 161 // MERGE: All or nothing. | |
| 162 case Combinator::MERGE: { | |
| 163 for (NodeDef* child_node : child_nodes_) { | |
| 164 if (!child_node->Snapshot(snapshot_builder, layer_builder, scene)) { | |
| 165 if (snapshot_builder->block_log()) { | |
| 166 *snapshot_builder->block_log() | |
| 167 << "Node with MERGE combinator blocked since " | |
| 168 "one of its children is blocked: " | |
| 169 << FormattedLabel(scene) << ", blocked child " | |
| 170 << child_node->FormattedLabel(scene) << std::endl; | |
| 171 } | |
| 172 return false; // blocked | |
| 173 } | |
| 174 } | |
| 175 return true; | |
| 176 } | |
| 177 | |
| 178 // PRUNE: Silently discard blocked children. | |
| 179 case Combinator::PRUNE: { | |
| 180 for (NodeDef* child_node : child_nodes_) { | |
| 181 RenderLayerBuilder child_layer_builder; | |
| 182 if (child_node->Snapshot(snapshot_builder, &child_layer_builder, | |
| 183 scene)) { | |
| 184 layer_builder->DrawLayer(child_layer_builder.Build()); | |
| 185 } | |
| 186 } | |
| 187 return true; | |
| 188 } | |
| 189 | |
| 190 // FALLBACK: Keep only the first unblocked child. | |
| 191 case Combinator::FALLBACK: { | |
| 192 if (child_nodes_.empty()) | |
| 193 return true; | |
| 194 for (NodeDef* child_node : child_nodes_) { | |
| 195 RenderLayerBuilder child_layer_builder; | |
| 196 if (child_node->Snapshot(snapshot_builder, &child_layer_builder, | |
| 197 scene)) { | |
| 198 layer_builder->DrawLayer(child_layer_builder.Build()); | |
| 199 return true; | |
| 200 } | |
| 201 } | |
| 202 if (snapshot_builder->block_log()) { | |
| 203 *snapshot_builder->block_log() | |
| 204 << "Node with FALLBACK combinator blocked since " | |
| 205 "all of its children are blocked: " | |
| 206 << FormattedLabel(scene) << std::endl; | |
| 207 } | |
| 208 return false; // blocked | |
| 209 } | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 std::string NodeDef::FormattedLabel(SceneDef* scene) { | |
| 214 std::ostringstream s; | |
| 215 s << scene->FormattedLabel() << "[" << node_id_ << "]"; | |
| 216 return s.str(); | |
|
abarth
2016/01/10 22:55:35
base::StringPrintf
jeffbrown
2016/01/16 03:28:32
Done.
| |
| 217 } | |
| 218 | |
| 219 bool NodeOp::Validate(SceneDef* scene, NodeDef* node, std::ostream& err) { | |
| 220 return true; | |
| 221 } | |
| 222 | |
| 223 RectNodeOp::RectNodeOp(const mojo::Rect& content_rect, | |
| 224 const mojo::gfx::composition::Color& color) | |
| 225 : content_rect_(content_rect), color_(color) {} | |
| 226 | |
| 227 RectNodeOp::~RectNodeOp() {} | |
| 228 | |
| 229 bool RectNodeOp::Snapshot(SnapshotBuilder* snapshot_builder, | |
| 230 RenderLayerBuilder* layer_builder, | |
| 231 SceneDef* scene, | |
| 232 NodeDef* node) { | |
| 233 if (!node->SnapshotChildren(snapshot_builder, layer_builder, scene)) | |
| 234 return false; | |
| 235 | |
| 236 SkPaint paint; | |
| 237 paint.setColor(ToSkColor(color_)); | |
| 238 layer_builder->DrawRect(ToSkRect(content_rect_), paint); | |
| 239 return true; | |
| 240 } | |
| 241 | |
| 242 ImageNodeOp::ImageNodeOp(const mojo::Rect& content_rect, | |
| 243 mojo::RectPtr image_rect, | |
| 244 uint32 image_resource_id, | |
| 245 mojo::gfx::composition::BlendPtr blend) | |
| 246 : content_rect_(content_rect), | |
| 247 image_rect_(image_rect.Pass()), | |
| 248 image_resource_id_(image_resource_id), | |
| 249 blend_(blend.Pass()) {} | |
| 250 | |
| 251 ImageNodeOp::~ImageNodeOp() {} | |
| 252 | |
| 253 bool ImageNodeOp::Validate(SceneDef* scene, NodeDef* node, std::ostream& err) { | |
| 254 image_resource_ = scene->FindImageResource(image_resource_id_); | |
| 255 if (!image_resource_) { | |
| 256 err << "Node refers to unknown or invalid image resource: " | |
| 257 << node->FormattedLabel(scene) | |
| 258 << ", image_resource_id=" << image_resource_id_; | |
| 259 return false; | |
| 260 } | |
| 261 return true; | |
| 262 } | |
| 263 | |
| 264 bool ImageNodeOp::Snapshot(SnapshotBuilder* snapshot_builder, | |
| 265 RenderLayerBuilder* layer_builder, | |
| 266 SceneDef* scene, | |
| 267 NodeDef* node) { | |
| 268 DCHECK(image_resource_); | |
| 269 | |
| 270 if (!image_resource_->image()) { | |
| 271 if (snapshot_builder->block_log()) { | |
| 272 *snapshot_builder->block_log() | |
| 273 << "Node blocked due to its referenced image " | |
| 274 "resource being unavailable: " | |
| 275 << node->FormattedLabel(scene) << std::endl; | |
| 276 } | |
| 277 return false; | |
| 278 } | |
| 279 | |
| 280 if (!node->SnapshotChildren(snapshot_builder, layer_builder, scene)) | |
| 281 return false; | |
| 282 | |
| 283 layer_builder->DrawImage( | |
| 284 image_resource_->image(), ToSkRect(content_rect_), | |
| 285 image_rect_ ? ToSkRect(*image_rect_) | |
| 286 : SkRect::MakeWH(image_resource_->image()->width(), | |
| 287 image_resource_->image()->height()), | |
| 288 blend_ ? ToSkPaint(*blend_) : SkPaint()); | |
| 289 return true; | |
| 290 } | |
| 291 | |
| 292 SceneNodeOp::SceneNodeOp(uint32_t scene_resource_id, uint32_t scene_version) | |
| 293 : scene_resource_id_(scene_resource_id), scene_version_(scene_version) {} | |
| 294 | |
| 295 SceneNodeOp::~SceneNodeOp() {} | |
| 296 | |
| 297 bool SceneNodeOp::Validate(SceneDef* scene, NodeDef* node, std::ostream& err) { | |
| 298 scene_resource_ = scene->FindSceneResource(scene_resource_id_); | |
| 299 if (!scene_resource_) { | |
| 300 err << "Node refers to unknown or invalid scene resource: " | |
| 301 << node->FormattedLabel(scene) | |
| 302 << ", scene_resource_id=" << scene_resource_id_; | |
| 303 return false; | |
| 304 } | |
| 305 return true; | |
| 306 } | |
| 307 | |
| 308 bool SceneNodeOp::Snapshot(SnapshotBuilder* snapshot_builder, | |
| 309 RenderLayerBuilder* layer_builder, | |
| 310 SceneDef* scene, | |
| 311 NodeDef* node) { | |
| 312 DCHECK(scene_resource_); | |
| 313 | |
| 314 SceneDef* referenced_scene = scene_resource_->referenced_scene(); | |
| 315 if (!referenced_scene) { | |
| 316 if (snapshot_builder->block_log()) { | |
| 317 *snapshot_builder->block_log() | |
| 318 << "Node blocked due to its referenced scene " | |
| 319 "resource being unavailable: " | |
| 320 << node->FormattedLabel(scene) << std::endl; | |
| 321 } | |
| 322 return false; | |
| 323 } | |
| 324 | |
| 325 uint32_t actual_version = referenced_scene->version(); | |
| 326 if (scene_version_ != mojo::gfx::composition::kSceneVersionNone && | |
| 327 actual_version != mojo::gfx::composition::kSceneVersionNone && | |
| 328 scene_version_ != actual_version) { | |
| 329 if (snapshot_builder->block_log()) { | |
| 330 *snapshot_builder->block_log() | |
| 331 << "Node blocked due to its referenced scene " | |
| 332 "resource not having the desired version: " | |
| 333 << node->FormattedLabel(scene) | |
| 334 << ", requested_version=" << scene_version_ | |
| 335 << ", actual_version=" << actual_version << std::endl; | |
| 336 } | |
| 337 return false; | |
| 338 } | |
| 339 | |
| 340 if (!node->SnapshotChildren(snapshot_builder, layer_builder, scene)) | |
| 341 return false; | |
| 342 | |
| 343 return referenced_scene->Snapshot(snapshot_builder, layer_builder); | |
| 344 } | |
| 345 | |
| 346 LayerNodeOp::LayerNodeOp(const mojo::Size& size, | |
| 347 mojo::gfx::composition::BlendPtr blend) | |
| 348 : size_(size), blend_(blend.Pass()) {} | |
| 349 | |
| 350 LayerNodeOp::~LayerNodeOp() {} | |
| 351 | |
| 352 bool LayerNodeOp::Snapshot(SnapshotBuilder* snapshot_builder, | |
| 353 RenderLayerBuilder* layer_builder, | |
| 354 SceneDef* scene, | |
| 355 NodeDef* node) { | |
| 356 SkRect content_rect = SkRect::MakeWH(size_.width, size_.height); | |
| 357 RenderLayerBuilder children_layer_builder(&content_rect); | |
| 358 if (!node->SnapshotChildren(snapshot_builder, &children_layer_builder, scene)) | |
| 359 return false; | |
| 360 | |
| 361 layer_builder->DrawSavedLayer(children_layer_builder.Build(), content_rect, | |
| 362 blend_ ? ToSkPaint(*blend_) : SkPaint()); | |
| 363 return true; | |
| 364 } | |
| 365 | |
| 366 } // namespace compositor | |
| OLD | NEW |