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

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

Issue 1774373002: Mozart: Implement hit testing. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-4
Patch Set: Created 4 years, 9 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/gfx/compositor/graph/node_def.h" 5 #include "services/gfx/compositor/graph/node_def.h"
6 6
7 #include <ostream> 7 #include <ostream>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "mojo/services/gfx/composition/cpp/formatting.h" 10 #include "mojo/services/gfx/composition/cpp/formatting.h"
11 #include "mojo/skia/type_converters.h" 11 #include "mojo/skia/type_converters.h"
12 #include "services/gfx/compositor/graph/scene_content.h" 12 #include "services/gfx/compositor/graph/scene_content.h"
13 #include "services/gfx/compositor/graph/scene_def.h" 13 #include "services/gfx/compositor/graph/scene_def.h"
14 #include "services/gfx/compositor/graph/snapshot.h" 14 #include "services/gfx/compositor/graph/snapshot.h"
15 #include "services/gfx/compositor/render/render_image.h" 15 #include "services/gfx/compositor/render/render_image.h"
16 #include "third_party/skia/include/core/SkCanvas.h" 16 #include "third_party/skia/include/core/SkCanvas.h"
17 #include "third_party/skia/include/core/SkColor.h" 17 #include "third_party/skia/include/core/SkColor.h"
18 #include "third_party/skia/include/core/SkMatrix.h"
18 #include "third_party/skia/include/core/SkPaint.h" 19 #include "third_party/skia/include/core/SkPaint.h"
20 #include "third_party/skia/include/core/SkPoint.h"
19 #include "third_party/skia/include/core/SkRect.h" 21 #include "third_party/skia/include/core/SkRect.h"
20 22
21 namespace compositor { 23 namespace compositor {
22 namespace { 24 namespace {
23 SkColor MakeSkColor(const mojo::gfx::composition::Color& color) { 25 SkColor MakeSkColor(const mojo::gfx::composition::Color& color) {
24 return SkColorSetARGBInline(color.alpha, color.red, color.green, color.blue); 26 return SkColorSetARGBInline(color.alpha, color.red, color.green, color.blue);
25 } 27 }
26 28
27 void SetPaintForBlend(SkPaint* paint, mojo::gfx::composition::Blend* blend) { 29 void SetPaintForBlend(SkPaint* paint, mojo::gfx::composition::Blend* blend) {
28 DCHECK(paint); 30 DCHECK(paint);
29 if (blend) 31 if (blend)
30 paint->setAlpha(blend->alpha); 32 paint->setAlpha(blend->alpha);
31 } 33 }
34
35 bool Contains(const SkRect& bounds, const SkPoint& point) {
36 return point.x() >= bounds.left() && point.x() < bounds.right() &&
37 point.y() >= bounds.top() && point.y() < bounds.bottom();
38 }
32 } // namespace 39 } // namespace
33 40
34 NodeDef::NodeDef(uint32_t node_id, 41 NodeDef::NodeDef(uint32_t node_id,
35 mojo::TransformPtr content_transform, 42 mojo::TransformPtr content_transform,
36 mojo::RectPtr content_clip, 43 mojo::RectPtr content_clip,
44 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
37 Combinator combinator, 45 Combinator combinator,
38 const std::vector<uint32_t>& child_node_ids) 46 const std::vector<uint32_t>& child_node_ids)
39 : node_id_(node_id), 47 : node_id_(node_id),
40 content_transform_(content_transform.Pass()), 48 content_transform_(content_transform.Pass()),
41 content_clip_(content_clip.Pass()), 49 content_clip_(content_clip.Pass()),
50 hit_test_behavior_(hit_test_behavior.Pass()),
42 combinator_(combinator), 51 combinator_(combinator),
43 child_node_ids_(child_node_ids) {} 52 child_node_ids_(child_node_ids) {}
44 53
45 NodeDef::~NodeDef() {} 54 NodeDef::~NodeDef() {}
46 55
47 std::string NodeDef::FormattedLabel(const SceneContent* content) const { 56 std::string NodeDef::FormattedLabel(const SceneContent* content) const {
48 return content->FormattedLabelForNode(node_id_); 57 return content->FormattedLabelForNode(node_id_);
49 } 58 }
50 59
51 bool NodeDef::RecordContent(SceneContentBuilder* builder) const { 60 bool NodeDef::RecordContent(SceneContentBuilder* builder) const {
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 DCHECK(canvas); 224 DCHECK(canvas);
216 225
217 TraverseSnapshottedChildren( 226 TraverseSnapshottedChildren(
218 content, snapshot, 227 content, snapshot,
219 [this, content, snapshot, canvas](const NodeDef* child_node) -> bool { 228 [this, content, snapshot, canvas](const NodeDef* child_node) -> bool {
220 child_node->RecordPicture(content, snapshot, canvas); 229 child_node->RecordPicture(content, snapshot, canvas);
221 return true; 230 return true;
222 }); 231 });
223 } 232 }
224 233
225 RectNodeDef::RectNodeDef(uint32_t node_id, 234 void NodeDef::HitTest(const SceneContent* content,
226 mojo::TransformPtr content_transform, 235 const Snapshot* snapshot,
227 mojo::RectPtr content_clip, 236 const SkPoint& global_point,
228 Combinator combinator, 237 const SkMatrix& parent_transform,
229 const std::vector<uint32_t>& child_node_ids, 238 bool* opaque,
230 const mojo::Rect& content_rect, 239 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
231 const mojo::gfx::composition::Color& color) 240 DCHECK(content);
241 DCHECK(snapshot);
242 DCHECK(opaque);
243 DCHECK(hits);
244
245 SkMatrix node_transform = parent_transform;
246 if (content_transform_)
247 node_transform.postConcat(content_transform_.To<SkMatrix>());
abarth 2016/03/09 04:02:48 I think you want to do this work in 4x4 matrices.
jeffbrown 2016/03/09 20:32:11 You're probably right. Noted for later since this
248 if (content_clip_) {
249 SkRect global_clip_rect;
250 node_transform.mapRect(&global_clip_rect, content_clip_->To<SkRect>());
abarth 2016/03/09 04:02:48 This isn't very efficient because you're doing a m
jeffbrown 2016/03/09 20:32:11 I previously wrote the code that way. The trade-o
251 if (!Contains(global_clip_rect, global_point))
252 return;
253 }
254
255 if (!hit_test_behavior_ || !hit_test_behavior_->prune)
256 HitTestInner(content, snapshot, global_point, node_transform, opaque, hits);
257
258 if (!hit_test_behavior_ ||
259 hit_test_behavior_->visibility ==
260 mojo::gfx::composition::HitTestBehavior::Visibility::INVISIBLE)
261 return;
262
263 if (hit_test_behavior_->hit_rect) {
264 SkRect global_hit_rect;
265 node_transform.mapRect(&global_hit_rect,
266 hit_test_behavior_->hit_rect->To<SkRect>());
267 if (!Contains(global_hit_rect, global_point))
268 return;
269 }
270
271 if (hit_test_behavior_->visibility ==
272 mojo::gfx::composition::HitTestBehavior::Visibility::OPAQUE)
273 *opaque = true;
274
275 SkMatrix inverse_node_transform;
276 if (!node_transform.invert(&inverse_node_transform)) {
277 // Matrix is singular!
278 // Return [0,0,0][0,0,0][0,0,1] (all zeroes except last component).
279 // This causes all points to be mapped to (0,0) when transformed.
280 inverse_node_transform.setScale(0.f, 0.f);
281 }
282
283 auto hit = mojo::gfx::composition::Hit::New();
284 hit->set_node(mojo::gfx::composition::NodeHit::New());
285 hit->get_node()->node_id = node_id_;
286 hit->get_node()->transform =
287 mojo::ConvertTo<mojo::TransformPtr>(inverse_node_transform);
288 hits->push_back(hit.Pass());
289 }
290
291 void NodeDef::HitTestInner(
abarth 2016/03/09 04:02:48 s/HitTestInner/HitTestChildren/ ?
jeffbrown 2016/03/09 20:32:11 Strictly speaking it's not just children since ref
292 const SceneContent* content,
293 const Snapshot* snapshot,
294 const SkPoint& global_point,
295 const SkMatrix& node_transform,
296 bool* opaque,
297 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
298 DCHECK(content);
299 DCHECK(snapshot);
300 DCHECK(opaque);
301 DCHECK(hits);
302
303 // TODO(jeffbrown): Implement a more efficient way to traverse children in
304 // reverse order.
305 std::vector<const NodeDef*> children;
306 TraverseSnapshottedChildren(
307 content, snapshot, [this, &children](const NodeDef* child_node) -> bool {
308 children.push_back(child_node);
309 return true;
310 });
311
312 for (auto it = children.crbegin(); it != children.crend(); ++it) {
313 (*it)->HitTest(content, snapshot, global_point, node_transform, opaque,
314 hits);
315 if (*opaque)
abarth 2016/03/09 04:02:48 In other systems, we've passed this value through
jeffbrown 2016/03/09 20:32:11 SceneContent::HitTest returns a SceneHitPtr as its
316 break;
317 }
318 }
319
320 RectNodeDef::RectNodeDef(
321 uint32_t node_id,
322 mojo::TransformPtr content_transform,
323 mojo::RectPtr content_clip,
324 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
325 Combinator combinator,
326 const std::vector<uint32_t>& child_node_ids,
327 const mojo::Rect& content_rect,
328 const mojo::gfx::composition::Color& color)
232 : NodeDef(node_id, 329 : NodeDef(node_id,
233 content_transform.Pass(), 330 content_transform.Pass(),
234 content_clip.Pass(), 331 content_clip.Pass(),
332 hit_test_behavior.Pass(),
235 combinator, 333 combinator,
236 child_node_ids), 334 child_node_ids),
237 content_rect_(content_rect), 335 content_rect_(content_rect),
238 color_(color) {} 336 color_(color) {}
239 337
240 RectNodeDef::~RectNodeDef() {} 338 RectNodeDef::~RectNodeDef() {}
241 339
242 void RectNodeDef::RecordPictureInner(const SceneContent* content, 340 void RectNodeDef::RecordPictureInner(const SceneContent* content,
243 const Snapshot* snapshot, 341 const Snapshot* snapshot,
244 SkCanvas* canvas) const { 342 SkCanvas* canvas) const {
245 DCHECK(content); 343 DCHECK(content);
246 DCHECK(snapshot); 344 DCHECK(snapshot);
247 DCHECK(canvas); 345 DCHECK(canvas);
248 346
249 SkPaint paint; 347 SkPaint paint;
250 paint.setColor(MakeSkColor(color_)); 348 paint.setColor(MakeSkColor(color_));
251 canvas->drawRect(content_rect_.To<SkRect>(), paint); 349 canvas->drawRect(content_rect_.To<SkRect>(), paint);
252 350
253 NodeDef::RecordPictureInner(content, snapshot, canvas); 351 NodeDef::RecordPictureInner(content, snapshot, canvas);
254 } 352 }
255 353
256 ImageNodeDef::ImageNodeDef(uint32_t node_id, 354 ImageNodeDef::ImageNodeDef(
257 mojo::TransformPtr content_transform, 355 uint32_t node_id,
258 mojo::RectPtr content_clip, 356 mojo::TransformPtr content_transform,
259 Combinator combinator, 357 mojo::RectPtr content_clip,
260 const std::vector<uint32_t>& child_node_ids, 358 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
261 const mojo::Rect& content_rect, 359 Combinator combinator,
262 mojo::RectPtr image_rect, 360 const std::vector<uint32_t>& child_node_ids,
263 uint32 image_resource_id, 361 const mojo::Rect& content_rect,
264 mojo::gfx::composition::BlendPtr blend) 362 mojo::RectPtr image_rect,
363 uint32 image_resource_id,
364 mojo::gfx::composition::BlendPtr blend)
265 : NodeDef(node_id, 365 : NodeDef(node_id,
266 content_transform.Pass(), 366 content_transform.Pass(),
267 content_clip.Pass(), 367 content_clip.Pass(),
368 hit_test_behavior.Pass(),
268 combinator, 369 combinator,
269 child_node_ids), 370 child_node_ids),
270 content_rect_(content_rect), 371 content_rect_(content_rect),
271 image_rect_(image_rect.Pass()), 372 image_rect_(image_rect.Pass()),
272 image_resource_id_(image_resource_id), 373 image_resource_id_(image_resource_id),
273 blend_(blend.Pass()) {} 374 blend_(blend.Pass()) {}
274 375
275 ImageNodeDef::~ImageNodeDef() {} 376 ImageNodeDef::~ImageNodeDef() {}
276 377
277 bool ImageNodeDef::RecordContent(SceneContentBuilder* builder) const { 378 bool ImageNodeDef::RecordContent(SceneContentBuilder* builder) const {
(...skipping 21 matching lines...) Expand all
299 canvas->drawImageRect(image_resource->image()->image().get(), 400 canvas->drawImageRect(image_resource->image()->image().get(),
300 image_rect_ 401 image_rect_
301 ? image_rect_->To<SkRect>() 402 ? image_rect_->To<SkRect>()
302 : SkRect::MakeWH(image_resource->image()->width(), 403 : SkRect::MakeWH(image_resource->image()->width(),
303 image_resource->image()->height()), 404 image_resource->image()->height()),
304 content_rect_.To<SkRect>(), &paint); 405 content_rect_.To<SkRect>(), &paint);
305 406
306 NodeDef::RecordPictureInner(content, snapshot, canvas); 407 NodeDef::RecordPictureInner(content, snapshot, canvas);
307 } 408 }
308 409
309 SceneNodeDef::SceneNodeDef(uint32_t node_id, 410 SceneNodeDef::SceneNodeDef(
310 mojo::TransformPtr content_transform, 411 uint32_t node_id,
311 mojo::RectPtr content_clip, 412 mojo::TransformPtr content_transform,
312 Combinator combinator, 413 mojo::RectPtr content_clip,
313 const std::vector<uint32_t>& child_node_ids, 414 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
314 uint32_t scene_resource_id, 415 Combinator combinator,
315 uint32_t scene_version) 416 const std::vector<uint32_t>& child_node_ids,
417 uint32_t scene_resource_id,
418 uint32_t scene_version)
316 : NodeDef(node_id, 419 : NodeDef(node_id,
317 content_transform.Pass(), 420 content_transform.Pass(),
318 content_clip.Pass(), 421 content_clip.Pass(),
422 hit_test_behavior.Pass(),
319 combinator, 423 combinator,
320 child_node_ids), 424 child_node_ids),
321 scene_resource_id_(scene_resource_id), 425 scene_resource_id_(scene_resource_id),
322 scene_version_(scene_version) {} 426 scene_version_(scene_version) {}
323 427
324 SceneNodeDef::~SceneNodeDef() {} 428 SceneNodeDef::~SceneNodeDef() {}
325 429
326 bool SceneNodeDef::RecordContent(SceneContentBuilder* builder) const { 430 bool SceneNodeDef::RecordContent(SceneContentBuilder* builder) const {
327 DCHECK(builder); 431 DCHECK(builder);
328 432
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 void SceneNodeDef::RecordPictureInner(const SceneContent* content, 465 void SceneNodeDef::RecordPictureInner(const SceneContent* content,
362 const Snapshot* snapshot, 466 const Snapshot* snapshot,
363 SkCanvas* canvas) const { 467 SkCanvas* canvas) const {
364 DCHECK(content); 468 DCHECK(content);
365 DCHECK(snapshot); 469 DCHECK(snapshot);
366 DCHECK(canvas); 470 DCHECK(canvas);
367 471
368 const SceneContent* resolved_content = 472 const SceneContent* resolved_content =
369 snapshot->GetResolvedSceneContent(this); 473 snapshot->GetResolvedSceneContent(this);
370 DCHECK(resolved_content); 474 DCHECK(resolved_content);
371 475 resolved_content->RecordPicture(snapshot, canvas);
372 const NodeDef* root_node = resolved_content->GetRootNodeIfExists();
373 DCHECK(root_node); // must have a root otherwise would have been blocked
374 root_node->RecordPicture(resolved_content, snapshot, canvas);
375 476
376 NodeDef::RecordPictureInner(content, snapshot, canvas); 477 NodeDef::RecordPictureInner(content, snapshot, canvas);
377 } 478 }
378 479
379 LayerNodeDef::LayerNodeDef(uint32_t node_id, 480 void SceneNodeDef::HitTestInner(
380 mojo::TransformPtr content_transform, 481 const SceneContent* content,
381 mojo::RectPtr content_clip, 482 const Snapshot* snapshot,
382 Combinator combinator, 483 const SkPoint& global_point,
383 const std::vector<uint32_t>& child_node_ids, 484 const SkMatrix& node_transform,
384 const mojo::Size& size, 485 bool* opaque,
385 mojo::gfx::composition::BlendPtr blend) 486 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
487 DCHECK(content);
488 DCHECK(snapshot);
489 DCHECK(opaque);
490 DCHECK(hits);
491
492 NodeDef::HitTestInner(content, snapshot, global_point, node_transform, opaque,
493 hits);
abarth 2016/03/09 04:02:48 Do we need to test opaque after calling this funct
jeffbrown 2016/03/09 20:32:11 Initially I didn't think so since I was imagining
494
495 const SceneContent* resolved_content =
496 snapshot->GetResolvedSceneContent(this);
497 DCHECK(resolved_content);
498 mojo::gfx::composition::SceneHitPtr scene_hit =
499 resolved_content->HitTest(snapshot, global_point, node_transform, opaque);
500 if (scene_hit) {
501 auto hit = mojo::gfx::composition::Hit::New();
502 hit->set_scene(scene_hit.Pass());
503 hits->push_back(hit.Pass());
504 }
505 }
506
507 LayerNodeDef::LayerNodeDef(
508 uint32_t node_id,
509 mojo::TransformPtr content_transform,
510 mojo::RectPtr content_clip,
511 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
512 Combinator combinator,
513 const std::vector<uint32_t>& child_node_ids,
514 const mojo::Size& size,
515 mojo::gfx::composition::BlendPtr blend)
386 : NodeDef(node_id, 516 : NodeDef(node_id,
387 content_transform.Pass(), 517 content_transform.Pass(),
388 content_clip.Pass(), 518 content_clip.Pass(),
519 hit_test_behavior.Pass(),
389 combinator, 520 combinator,
390 child_node_ids), 521 child_node_ids),
391 size_(size), 522 size_(size),
392 blend_(blend.Pass()) {} 523 blend_(blend.Pass()) {}
393 524
394 LayerNodeDef::~LayerNodeDef() {} 525 LayerNodeDef::~LayerNodeDef() {}
395 526
396 void LayerNodeDef::RecordPictureInner(const SceneContent* content, 527 void LayerNodeDef::RecordPictureInner(const SceneContent* content,
397 const Snapshot* snapshot, 528 const Snapshot* snapshot,
398 SkCanvas* canvas) const { 529 SkCanvas* canvas) const {
399 DCHECK(content); 530 DCHECK(content);
400 DCHECK(snapshot); 531 DCHECK(snapshot);
401 DCHECK(canvas); 532 DCHECK(canvas);
402 533
403 SkPaint paint; 534 SkPaint paint;
404 SetPaintForBlend(&paint, blend_.get()); 535 SetPaintForBlend(&paint, blend_.get());
405 536
406 canvas->saveLayer(SkRect::MakeWH(size_.width, size_.height), &paint); 537 canvas->saveLayer(SkRect::MakeWH(size_.width, size_.height), &paint);
407 NodeDef::RecordPictureInner(content, snapshot, canvas); 538 NodeDef::RecordPictureInner(content, snapshot, canvas);
408 canvas->restore(); 539 canvas->restore();
409 } 540 }
410 541
411 } // namespace compositor 542 } // namespace compositor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698