Chromium Code Reviews| 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 |
| index 6a1dfc9a974083244d8bf59ee8bcbe6a2a86f066..6092bab1c79677760dafc30201125752b4960b90 100644 |
| --- a/services/gfx/compositor/graph/node_def.cc |
| +++ b/services/gfx/compositor/graph/node_def.cc |
| @@ -15,7 +15,9 @@ |
| #include "services/gfx/compositor/render/render_image.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| +#include "third_party/skia/include/core/SkMatrix.h" |
| #include "third_party/skia/include/core/SkPaint.h" |
| +#include "third_party/skia/include/core/SkPoint.h" |
| #include "third_party/skia/include/core/SkRect.h" |
| namespace compositor { |
| @@ -29,16 +31,23 @@ void SetPaintForBlend(SkPaint* paint, mojo::gfx::composition::Blend* blend) { |
| if (blend) |
| paint->setAlpha(blend->alpha); |
| } |
| + |
| +bool Contains(const SkRect& bounds, const SkPoint& point) { |
| + return point.x() >= bounds.left() && point.x() < bounds.right() && |
| + point.y() >= bounds.top() && point.y() < bounds.bottom(); |
| +} |
| } // namespace |
| NodeDef::NodeDef(uint32_t node_id, |
| mojo::TransformPtr content_transform, |
| mojo::RectPtr content_clip, |
| + mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
| Combinator combinator, |
| const std::vector<uint32_t>& child_node_ids) |
| : node_id_(node_id), |
| content_transform_(content_transform.Pass()), |
| content_clip_(content_clip.Pass()), |
| + hit_test_behavior_(hit_test_behavior.Pass()), |
| combinator_(combinator), |
| child_node_ids_(child_node_ids) {} |
| @@ -222,16 +231,105 @@ void NodeDef::RecordPictureInner(const SceneContent* content, |
| }); |
| } |
| -RectNodeDef::RectNodeDef(uint32_t node_id, |
| - mojo::TransformPtr content_transform, |
| - mojo::RectPtr content_clip, |
| - Combinator combinator, |
| - const std::vector<uint32_t>& child_node_ids, |
| - const mojo::Rect& content_rect, |
| - const mojo::gfx::composition::Color& color) |
| +void NodeDef::HitTest(const SceneContent* content, |
| + const Snapshot* snapshot, |
| + const SkPoint& global_point, |
| + const SkMatrix& parent_transform, |
| + bool* opaque, |
| + mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
| + DCHECK(content); |
| + DCHECK(snapshot); |
| + DCHECK(opaque); |
| + DCHECK(hits); |
| + |
| + SkMatrix node_transform = parent_transform; |
| + if (content_transform_) |
| + 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
|
| + if (content_clip_) { |
| + SkRect global_clip_rect; |
| + 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
|
| + if (!Contains(global_clip_rect, global_point)) |
| + return; |
| + } |
| + |
| + if (!hit_test_behavior_ || !hit_test_behavior_->prune) |
| + HitTestInner(content, snapshot, global_point, node_transform, opaque, hits); |
| + |
| + if (!hit_test_behavior_ || |
| + hit_test_behavior_->visibility == |
| + mojo::gfx::composition::HitTestBehavior::Visibility::INVISIBLE) |
| + return; |
| + |
| + if (hit_test_behavior_->hit_rect) { |
| + SkRect global_hit_rect; |
| + node_transform.mapRect(&global_hit_rect, |
| + hit_test_behavior_->hit_rect->To<SkRect>()); |
| + if (!Contains(global_hit_rect, global_point)) |
| + return; |
| + } |
| + |
| + if (hit_test_behavior_->visibility == |
| + mojo::gfx::composition::HitTestBehavior::Visibility::OPAQUE) |
| + *opaque = true; |
| + |
| + SkMatrix inverse_node_transform; |
| + if (!node_transform.invert(&inverse_node_transform)) { |
| + // Matrix is singular! |
| + // Return [0,0,0][0,0,0][0,0,1] (all zeroes except last component). |
| + // This causes all points to be mapped to (0,0) when transformed. |
| + inverse_node_transform.setScale(0.f, 0.f); |
| + } |
| + |
| + auto hit = mojo::gfx::composition::Hit::New(); |
| + hit->set_node(mojo::gfx::composition::NodeHit::New()); |
| + hit->get_node()->node_id = node_id_; |
| + hit->get_node()->transform = |
| + mojo::ConvertTo<mojo::TransformPtr>(inverse_node_transform); |
| + hits->push_back(hit.Pass()); |
| +} |
| + |
| +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
|
| + const SceneContent* content, |
| + const Snapshot* snapshot, |
| + const SkPoint& global_point, |
| + const SkMatrix& node_transform, |
| + bool* opaque, |
| + mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
| + DCHECK(content); |
| + DCHECK(snapshot); |
| + DCHECK(opaque); |
| + DCHECK(hits); |
| + |
| + // TODO(jeffbrown): Implement a more efficient way to traverse children in |
| + // reverse order. |
| + std::vector<const NodeDef*> children; |
| + TraverseSnapshottedChildren( |
| + content, snapshot, [this, &children](const NodeDef* child_node) -> bool { |
| + children.push_back(child_node); |
| + return true; |
| + }); |
| + |
| + for (auto it = children.crbegin(); it != children.crend(); ++it) { |
| + (*it)->HitTest(content, snapshot, global_point, node_transform, opaque, |
| + hits); |
| + 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
|
| + break; |
| + } |
| +} |
| + |
| +RectNodeDef::RectNodeDef( |
| + uint32_t node_id, |
| + mojo::TransformPtr content_transform, |
| + mojo::RectPtr content_clip, |
| + mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
| + Combinator combinator, |
| + const std::vector<uint32_t>& child_node_ids, |
| + const mojo::Rect& content_rect, |
| + const mojo::gfx::composition::Color& color) |
| : NodeDef(node_id, |
| content_transform.Pass(), |
| content_clip.Pass(), |
| + hit_test_behavior.Pass(), |
| combinator, |
| child_node_ids), |
| content_rect_(content_rect), |
| @@ -253,18 +351,21 @@ void RectNodeDef::RecordPictureInner(const SceneContent* content, |
| NodeDef::RecordPictureInner(content, snapshot, canvas); |
| } |
| -ImageNodeDef::ImageNodeDef(uint32_t node_id, |
| - mojo::TransformPtr content_transform, |
| - mojo::RectPtr content_clip, |
| - Combinator combinator, |
| - const std::vector<uint32_t>& child_node_ids, |
| - const mojo::Rect& content_rect, |
| - mojo::RectPtr image_rect, |
| - uint32 image_resource_id, |
| - mojo::gfx::composition::BlendPtr blend) |
| +ImageNodeDef::ImageNodeDef( |
| + uint32_t node_id, |
| + mojo::TransformPtr content_transform, |
| + mojo::RectPtr content_clip, |
| + mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
| + Combinator combinator, |
| + const std::vector<uint32_t>& child_node_ids, |
| + const mojo::Rect& content_rect, |
| + mojo::RectPtr image_rect, |
| + uint32 image_resource_id, |
| + mojo::gfx::composition::BlendPtr blend) |
| : NodeDef(node_id, |
| content_transform.Pass(), |
| content_clip.Pass(), |
| + hit_test_behavior.Pass(), |
| combinator, |
| child_node_ids), |
| content_rect_(content_rect), |
| @@ -306,16 +407,19 @@ void ImageNodeDef::RecordPictureInner(const SceneContent* content, |
| NodeDef::RecordPictureInner(content, snapshot, canvas); |
| } |
| -SceneNodeDef::SceneNodeDef(uint32_t node_id, |
| - mojo::TransformPtr content_transform, |
| - mojo::RectPtr content_clip, |
| - Combinator combinator, |
| - const std::vector<uint32_t>& child_node_ids, |
| - uint32_t scene_resource_id, |
| - uint32_t scene_version) |
| +SceneNodeDef::SceneNodeDef( |
| + uint32_t node_id, |
| + mojo::TransformPtr content_transform, |
| + mojo::RectPtr content_clip, |
| + mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
| + Combinator combinator, |
| + const std::vector<uint32_t>& child_node_ids, |
| + uint32_t scene_resource_id, |
| + uint32_t scene_version) |
| : NodeDef(node_id, |
| content_transform.Pass(), |
| content_clip.Pass(), |
| + hit_test_behavior.Pass(), |
| combinator, |
| child_node_ids), |
| scene_resource_id_(scene_resource_id), |
| @@ -368,24 +472,51 @@ void SceneNodeDef::RecordPictureInner(const SceneContent* content, |
| const SceneContent* resolved_content = |
| snapshot->GetResolvedSceneContent(this); |
| DCHECK(resolved_content); |
| - |
| - const NodeDef* root_node = resolved_content->GetRootNodeIfExists(); |
| - DCHECK(root_node); // must have a root otherwise would have been blocked |
| - root_node->RecordPicture(resolved_content, snapshot, canvas); |
| + resolved_content->RecordPicture(snapshot, canvas); |
| NodeDef::RecordPictureInner(content, snapshot, canvas); |
| } |
| -LayerNodeDef::LayerNodeDef(uint32_t node_id, |
| - mojo::TransformPtr content_transform, |
| - mojo::RectPtr content_clip, |
| - Combinator combinator, |
| - const std::vector<uint32_t>& child_node_ids, |
| - const mojo::Size& size, |
| - mojo::gfx::composition::BlendPtr blend) |
| +void SceneNodeDef::HitTestInner( |
| + const SceneContent* content, |
| + const Snapshot* snapshot, |
| + const SkPoint& global_point, |
| + const SkMatrix& node_transform, |
| + bool* opaque, |
| + mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
| + DCHECK(content); |
| + DCHECK(snapshot); |
| + DCHECK(opaque); |
| + DCHECK(hits); |
| + |
| + NodeDef::HitTestInner(content, snapshot, global_point, node_transform, opaque, |
| + 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
|
| + |
| + const SceneContent* resolved_content = |
| + snapshot->GetResolvedSceneContent(this); |
| + DCHECK(resolved_content); |
| + mojo::gfx::composition::SceneHitPtr scene_hit = |
| + resolved_content->HitTest(snapshot, global_point, node_transform, opaque); |
| + if (scene_hit) { |
| + auto hit = mojo::gfx::composition::Hit::New(); |
| + hit->set_scene(scene_hit.Pass()); |
| + hits->push_back(hit.Pass()); |
| + } |
| +} |
| + |
| +LayerNodeDef::LayerNodeDef( |
| + uint32_t node_id, |
| + mojo::TransformPtr content_transform, |
| + mojo::RectPtr content_clip, |
| + mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
| + Combinator combinator, |
| + const std::vector<uint32_t>& child_node_ids, |
| + const mojo::Size& size, |
| + mojo::gfx::composition::BlendPtr blend) |
| : NodeDef(node_id, |
| content_transform.Pass(), |
| content_clip.Pass(), |
| + hit_test_behavior.Pass(), |
| combinator, |
| child_node_ids), |
| size_(size), |