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

Side by Side Diff: services/gfx/compositor/graph/node_def.cc

Issue 1874593002: Mozart: Rename scene graph classes. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-2
Patch Set: Created 4 years, 8 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 unified diff | Download patch
« no previous file with comments | « services/gfx/compositor/graph/node_def.h ('k') | services/gfx/compositor/graph/nodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 <ostream>
8
9 #include "base/logging.h"
10 #include "mojo/services/gfx/composition/cpp/formatting.h"
11 #include "mojo/skia/type_converters.h"
12 #include "services/gfx/compositor/graph/scene_content.h"
13 #include "services/gfx/compositor/graph/scene_def.h"
14 #include "services/gfx/compositor/graph/snapshot.h"
15 #include "services/gfx/compositor/graph/transform_pair.h"
16 #include "services/gfx/compositor/render/render_image.h"
17 #include "third_party/skia/include/core/SkCanvas.h"
18 #include "third_party/skia/include/core/SkColor.h"
19 #include "third_party/skia/include/core/SkMatrix.h"
20 #include "third_party/skia/include/core/SkPaint.h"
21 #include "third_party/skia/include/core/SkPoint.h"
22 #include "third_party/skia/include/core/SkRect.h"
23 #include "third_party/skia/include/utils/SkMatrix44.h"
24
25 namespace compositor {
26 namespace {
27 SkColor MakeSkColor(const mojo::gfx::composition::Color& color) {
28 return SkColorSetARGBInline(color.alpha, color.red, color.green, color.blue);
29 }
30
31 void SetPaintForBlend(SkPaint* paint, mojo::gfx::composition::Blend* blend) {
32 DCHECK(paint);
33 if (blend)
34 paint->setAlpha(blend->alpha);
35 }
36
37 bool Contains(const SkRect& bounds, const SkPoint& point) {
38 return point.x() >= bounds.left() && point.x() < bounds.right() &&
39 point.y() >= bounds.top() && point.y() < bounds.bottom();
40 }
41 } // namespace
42
43 NodeDef::NodeDef(uint32_t node_id,
44 std::unique_ptr<TransformPair> content_transform,
45 mojo::RectFPtr content_clip,
46 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
47 Combinator combinator,
48 const std::vector<uint32_t>& child_node_ids)
49 : node_id_(node_id),
50 content_transform_(std::move(content_transform)),
51 content_clip_(content_clip.Pass()),
52 hit_test_behavior_(hit_test_behavior.Pass()),
53 combinator_(combinator),
54 child_node_ids_(child_node_ids) {}
55
56 NodeDef::~NodeDef() {}
57
58 std::string NodeDef::FormattedLabel(const SceneContent* content) const {
59 return content->FormattedLabelForNode(node_id_);
60 }
61
62 bool NodeDef::RecordContent(SceneContentBuilder* builder) const {
63 DCHECK(builder);
64
65 for (const auto& child_node_id : child_node_ids_) {
66 if (!builder->RequireNode(child_node_id, node_id_))
67 return false;
68 }
69 return true;
70 }
71
72 Snapshot::Disposition NodeDef::RecordSnapshot(const SceneContent* content,
73 SnapshotBuilder* builder) const {
74 DCHECK(content);
75 DCHECK(builder);
76
77 switch (combinator_) {
78 // MERGE: All or nothing.
79 case Combinator::MERGE: {
80 for (uint32_t child_node_id : child_node_ids_) {
81 const NodeDef* child_node = content->GetNode(child_node_id);
82 DCHECK(child_node);
83 Snapshot::Disposition disposition =
84 builder->SnapshotNode(child_node, content);
85 if (disposition == Snapshot::Disposition::kCycle)
86 return disposition;
87 if (disposition == Snapshot::Disposition::kBlocked) {
88 if (builder->block_log()) {
89 *builder->block_log()
90 << "Node with MERGE combinator blocked since "
91 "one of its children is blocked: "
92 << FormattedLabel(content) << ", blocked child "
93 << child_node->FormattedLabel(content) << std::endl;
94 }
95 return disposition;
96 }
97 }
98 return Snapshot::Disposition::kSuccess;
99 }
100
101 // PRUNE: Silently discard blocked children.
102 case Combinator::PRUNE: {
103 for (uint32_t child_node_id : child_node_ids_) {
104 const NodeDef* child_node = content->GetNode(child_node_id);
105 DCHECK(child_node);
106 Snapshot::Disposition disposition =
107 builder->SnapshotNode(child_node, content);
108 if (disposition == Snapshot::Disposition::kCycle)
109 return disposition;
110 }
111 return Snapshot::Disposition::kSuccess;
112 }
113
114 // FALLBACK: Keep only the first unblocked child.
115 case Combinator::FALLBACK: {
116 if (child_node_ids_.empty())
117 return Snapshot::Disposition::kSuccess;
118 for (uint32_t child_node_id : child_node_ids_) {
119 const NodeDef* child_node = content->GetNode(child_node_id);
120 DCHECK(child_node);
121 Snapshot::Disposition disposition =
122 builder->SnapshotNode(child_node, content);
123 if (disposition != Snapshot::Disposition::kBlocked)
124 return disposition;
125 }
126 if (builder->block_log()) {
127 *builder->block_log() << "Node with FALLBACK combinator blocked since "
128 "all of its children are blocked: "
129 << FormattedLabel(content) << std::endl;
130 }
131 return Snapshot::Disposition::kBlocked;
132 }
133
134 default: {
135 if (builder->block_log()) {
136 *builder->block_log()
137 << "Unrecognized combinator: " << FormattedLabel(content)
138 << std::endl;
139 }
140 return Snapshot::Disposition::kBlocked;
141 }
142 }
143 }
144
145 template <typename Func>
146 void NodeDef::TraverseSnapshottedChildren(const SceneContent* content,
147 const Snapshot* snapshot,
148 const Func& func) const {
149 DCHECK(content);
150 DCHECK(snapshot);
151
152 switch (combinator_) {
153 // MERGE: All or nothing.
154 case Combinator::MERGE: {
155 for (uint32_t child_node_id : child_node_ids_) {
156 const NodeDef* child_node = content->GetNode(child_node_id);
157 DCHECK(child_node);
158 DCHECK(!snapshot->IsNodeBlocked(child_node));
159 if (!func(child_node))
160 return;
161 }
162 return;
163 }
164
165 // PRUNE: Silently discard blocked children.
166 case Combinator::PRUNE: {
167 for (uint32_t child_node_id : child_node_ids_) {
168 const NodeDef* child_node = content->GetNode(child_node_id);
169 DCHECK(child_node);
170 if (!snapshot->IsNodeBlocked(child_node) && !func(child_node))
171 return;
172 }
173 return;
174 }
175
176 // FALLBACK: Keep only the first unblocked child.
177 case Combinator::FALLBACK: {
178 if (child_node_ids_.empty())
179 return;
180 for (uint32_t child_node_id : child_node_ids_) {
181 const NodeDef* child_node = content->GetNode(child_node_id);
182 DCHECK(child_node);
183 if (!snapshot->IsNodeBlocked(child_node)) {
184 func(child_node); // don't care about the result because we
185 return; // always stop after the first one
186 }
187 }
188 NOTREACHED();
189 return;
190 }
191
192 default: {
193 NOTREACHED();
194 return;
195 }
196 }
197 }
198
199 void NodeDef::RecordPicture(const SceneContent* content,
200 const Snapshot* snapshot,
201 SkCanvas* canvas) const {
202 DCHECK(content);
203 DCHECK(snapshot);
204 DCHECK(canvas);
205
206 const bool must_save = content_transform_ || content_clip_;
207 if (must_save) {
208 canvas->save();
209 if (content_transform_)
210 canvas->concat(content_transform_->forward());
211 if (content_clip_)
212 canvas->clipRect(content_clip_->To<SkRect>());
213 }
214
215 RecordPictureInner(content, snapshot, canvas);
216
217 if (must_save)
218 canvas->restore();
219 }
220
221 void NodeDef::RecordPictureInner(const SceneContent* content,
222 const Snapshot* snapshot,
223 SkCanvas* canvas) const {
224 DCHECK(content);
225 DCHECK(snapshot);
226 DCHECK(canvas);
227
228 TraverseSnapshottedChildren(
229 content, snapshot,
230 [this, content, snapshot, canvas](const NodeDef* child_node) -> bool {
231 child_node->RecordPicture(content, snapshot, canvas);
232 return true;
233 });
234 }
235
236 bool NodeDef::HitTest(const SceneContent* content,
237 const Snapshot* snapshot,
238 const SkPoint& parent_point,
239 const SkMatrix44& global_to_parent_transform,
240 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
241 DCHECK(content);
242 DCHECK(snapshot);
243 DCHECK(hits);
244
245 // TODO(jeffbrown): These calculations should probably be happening using
246 // a 4x4 matrix instead.
247 SkPoint local_point(parent_point);
248 SkMatrix global_to_local_transform(global_to_parent_transform);
249 if (content_transform_) {
250 // TODO(jeffbrown): Defer matrix multiplications using a matrix stack.
251 local_point = content_transform_->InverseMapPoint(parent_point);
252 global_to_local_transform.preConcat(content_transform_->GetInverse());
253 }
254
255 if (content_clip_ && !Contains(content_clip_->To<SkRect>(), local_point))
256 return false;
257
258 bool opaque_children = false;
259 if (!hit_test_behavior_ || !hit_test_behavior_->prune) {
260 opaque_children = HitTestInner(content, snapshot, local_point,
261 global_to_local_transform, hits);
262 }
263
264 return HitTestSelf(content, snapshot, local_point, global_to_local_transform,
265 hits) ||
266 opaque_children;
267 }
268
269 bool NodeDef::HitTestInner(
270 const SceneContent* content,
271 const Snapshot* snapshot,
272 const SkPoint& local_point,
273 const SkMatrix44& global_to_local_transform,
274 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
275 DCHECK(content);
276 DCHECK(snapshot);
277 DCHECK(hits);
278
279 // TODO(jeffbrown): Implement a more efficient way to traverse children in
280 // reverse order.
281 std::vector<const NodeDef*> children;
282 TraverseSnapshottedChildren(
283 content, snapshot, [this, &children](const NodeDef* child_node) -> bool {
284 children.push_back(child_node);
285 return true;
286 });
287
288 for (auto it = children.crbegin(); it != children.crend(); ++it) {
289 if ((*it)->HitTest(content, snapshot, local_point,
290 global_to_local_transform, hits))
291 return true; // opaque child covering siblings
292 }
293 return false;
294 }
295
296 bool NodeDef::HitTestSelf(
297 const SceneContent* content,
298 const Snapshot* snapshot,
299 const SkPoint& local_point,
300 const SkMatrix44& global_to_local_transform,
301 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
302 DCHECK(content);
303 DCHECK(snapshot);
304 DCHECK(hits);
305
306 if (!hit_test_behavior_ ||
307 hit_test_behavior_->visibility ==
308 mojo::gfx::composition::HitTestBehavior::Visibility::INVISIBLE)
309 return false;
310
311 if (hit_test_behavior_->hit_rect &&
312 !Contains(hit_test_behavior_->hit_rect->To<SkRect>(), local_point))
313 return false;
314
315 auto hit = mojo::gfx::composition::Hit::New();
316 hit->set_node(mojo::gfx::composition::NodeHit::New());
317 hit->get_node()->node_id = node_id_;
318 hit->get_node()->transform =
319 mojo::ConvertTo<mojo::TransformPtr>(global_to_local_transform);
320 hits->push_back(hit.Pass());
321 return hit_test_behavior_->visibility ==
322 mojo::gfx::composition::HitTestBehavior::Visibility::OPAQUE;
323 }
324
325 RectNodeDef::RectNodeDef(
326 uint32_t node_id,
327 std::unique_ptr<TransformPair> content_transform,
328 mojo::RectFPtr content_clip,
329 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
330 Combinator combinator,
331 const std::vector<uint32_t>& child_node_ids,
332 const mojo::RectF& content_rect,
333 const mojo::gfx::composition::Color& color)
334 : NodeDef(node_id,
335 std::move(content_transform),
336 content_clip.Pass(),
337 hit_test_behavior.Pass(),
338 combinator,
339 child_node_ids),
340 content_rect_(content_rect),
341 color_(color) {}
342
343 RectNodeDef::~RectNodeDef() {}
344
345 void RectNodeDef::RecordPictureInner(const SceneContent* content,
346 const Snapshot* snapshot,
347 SkCanvas* canvas) const {
348 DCHECK(content);
349 DCHECK(snapshot);
350 DCHECK(canvas);
351
352 SkPaint paint;
353 paint.setColor(MakeSkColor(color_));
354 canvas->drawRect(content_rect_.To<SkRect>(), paint);
355
356 NodeDef::RecordPictureInner(content, snapshot, canvas);
357 }
358
359 ImageNodeDef::ImageNodeDef(
360 uint32_t node_id,
361 std::unique_ptr<TransformPair> content_transform,
362 mojo::RectFPtr content_clip,
363 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
364 Combinator combinator,
365 const std::vector<uint32_t>& child_node_ids,
366 const mojo::RectF& content_rect,
367 mojo::RectFPtr image_rect,
368 uint32 image_resource_id,
369 mojo::gfx::composition::BlendPtr blend)
370 : NodeDef(node_id,
371 std::move(content_transform),
372 content_clip.Pass(),
373 hit_test_behavior.Pass(),
374 combinator,
375 child_node_ids),
376 content_rect_(content_rect),
377 image_rect_(image_rect.Pass()),
378 image_resource_id_(image_resource_id),
379 blend_(blend.Pass()) {}
380
381 ImageNodeDef::~ImageNodeDef() {}
382
383 bool ImageNodeDef::RecordContent(SceneContentBuilder* builder) const {
384 DCHECK(builder);
385
386 return NodeDef::RecordContent(builder) &&
387 builder->RequireResource(image_resource_id_, ResourceDef::Type::kImage,
388 node_id());
389 }
390
391 void ImageNodeDef::RecordPictureInner(const SceneContent* content,
392 const Snapshot* snapshot,
393 SkCanvas* canvas) const {
394 DCHECK(content);
395 DCHECK(snapshot);
396 DCHECK(canvas);
397
398 auto image_resource = static_cast<const ImageResourceDef*>(
399 content->GetResource(image_resource_id_, ResourceDef::Type::kImage));
400 DCHECK(image_resource);
401
402 SkPaint paint;
403 SetPaintForBlend(&paint, blend_.get());
404
405 canvas->drawImageRect(image_resource->image()->image().get(),
406 image_rect_
407 ? image_rect_->To<SkRect>()
408 : SkRect::MakeWH(image_resource->image()->width(),
409 image_resource->image()->height()),
410 content_rect_.To<SkRect>(), &paint);
411
412 NodeDef::RecordPictureInner(content, snapshot, canvas);
413 }
414
415 SceneNodeDef::SceneNodeDef(
416 uint32_t node_id,
417 std::unique_ptr<TransformPair> content_transform,
418 mojo::RectFPtr content_clip,
419 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
420 Combinator combinator,
421 const std::vector<uint32_t>& child_node_ids,
422 uint32_t scene_resource_id,
423 uint32_t scene_version)
424 : NodeDef(node_id,
425 std::move(content_transform),
426 content_clip.Pass(),
427 hit_test_behavior.Pass(),
428 combinator,
429 child_node_ids),
430 scene_resource_id_(scene_resource_id),
431 scene_version_(scene_version) {}
432
433 SceneNodeDef::~SceneNodeDef() {}
434
435 bool SceneNodeDef::RecordContent(SceneContentBuilder* builder) const {
436 DCHECK(builder);
437
438 return NodeDef::RecordContent(builder) &&
439 builder->RequireResource(scene_resource_id_, ResourceDef::Type::kScene,
440 node_id());
441 }
442
443 Snapshot::Disposition SceneNodeDef::RecordSnapshot(
444 const SceneContent* content,
445 SnapshotBuilder* builder) const {
446 DCHECK(content);
447 DCHECK(builder);
448
449 auto scene_resource = static_cast<const SceneResourceDef*>(
450 content->GetResource(scene_resource_id_, ResourceDef::Type::kScene));
451 DCHECK(scene_resource);
452
453 SceneDef* referenced_scene = scene_resource->referenced_scene().get();
454 if (!referenced_scene) {
455 if (builder->block_log()) {
456 *builder->block_log()
457 << "Scene node blocked because its referenced scene is unavailable: "
458 << FormattedLabel(content) << std::endl;
459 }
460 return Snapshot::Disposition::kBlocked;
461 }
462
463 Snapshot::Disposition disposition =
464 builder->SnapshotScene(referenced_scene, scene_version_, this, content);
465 if (disposition != Snapshot::Disposition::kSuccess)
466 return disposition;
467 return NodeDef::RecordSnapshot(content, builder);
468 }
469
470 void SceneNodeDef::RecordPictureInner(const SceneContent* content,
471 const Snapshot* snapshot,
472 SkCanvas* canvas) const {
473 DCHECK(content);
474 DCHECK(snapshot);
475 DCHECK(canvas);
476
477 const SceneContent* resolved_content =
478 snapshot->GetResolvedSceneContent(this);
479 DCHECK(resolved_content);
480 resolved_content->RecordPicture(snapshot, canvas);
481
482 NodeDef::RecordPictureInner(content, snapshot, canvas);
483 }
484
485 bool SceneNodeDef::HitTestInner(
486 const SceneContent* content,
487 const Snapshot* snapshot,
488 const SkPoint& local_point,
489 const SkMatrix44& global_to_local_transform,
490 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
491 DCHECK(content);
492 DCHECK(snapshot);
493 DCHECK(hits);
494
495 if (NodeDef::HitTestInner(content, snapshot, local_point,
496 global_to_local_transform, hits))
497 return true; // opaque child covering referenced scene
498
499 const SceneContent* resolved_content =
500 snapshot->GetResolvedSceneContent(this);
501 DCHECK(resolved_content);
502
503 mojo::gfx::composition::SceneHitPtr scene_hit;
504 bool opaque = resolved_content->HitTest(
505 snapshot, local_point, global_to_local_transform, &scene_hit);
506 if (scene_hit) {
507 auto hit = mojo::gfx::composition::Hit::New();
508 hit->set_scene(scene_hit.Pass());
509 hits->push_back(hit.Pass());
510 }
511 return opaque;
512 }
513
514 LayerNodeDef::LayerNodeDef(
515 uint32_t node_id,
516 std::unique_ptr<TransformPair> content_transform,
517 mojo::RectFPtr content_clip,
518 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
519 Combinator combinator,
520 const std::vector<uint32_t>& child_node_ids,
521 const mojo::RectF& layer_rect,
522 mojo::gfx::composition::BlendPtr blend)
523 : NodeDef(node_id,
524 std::move(content_transform),
525 content_clip.Pass(),
526 hit_test_behavior.Pass(),
527 combinator,
528 child_node_ids),
529 layer_rect_(layer_rect),
530 blend_(blend.Pass()) {}
531
532 LayerNodeDef::~LayerNodeDef() {}
533
534 void LayerNodeDef::RecordPictureInner(const SceneContent* content,
535 const Snapshot* snapshot,
536 SkCanvas* canvas) const {
537 DCHECK(content);
538 DCHECK(snapshot);
539 DCHECK(canvas);
540
541 SkPaint paint;
542 SetPaintForBlend(&paint, blend_.get());
543
544 canvas->saveLayer(layer_rect_.To<SkRect>(), &paint);
545 NodeDef::RecordPictureInner(content, snapshot, canvas);
546 canvas->restore();
547 }
548
549 } // namespace compositor
OLDNEW
« no previous file with comments | « services/gfx/compositor/graph/node_def.h ('k') | services/gfx/compositor/graph/nodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698