OLD | NEW |
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 Loading... |
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 bool NodeDef::HitTest(const SceneContent* content, |
226 mojo::TransformPtr content_transform, | 235 const Snapshot* snapshot, |
227 mojo::RectPtr content_clip, | 236 const SkPoint& parent_point, |
228 Combinator combinator, | 237 const SkMatrix& global_to_parent_transform, |
229 const std::vector<uint32_t>& child_node_ids, | 238 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
230 const mojo::Rect& content_rect, | 239 DCHECK(content); |
231 const mojo::gfx::composition::Color& color) | 240 DCHECK(snapshot); |
| 241 DCHECK(hits); |
| 242 |
| 243 // TODO(jeffbrown): These calculations should probably be happening using |
| 244 // a 4x4 matrix instead. |
| 245 SkPoint local_point = parent_point; |
| 246 SkMatrix global_to_local_transform = global_to_parent_transform; |
| 247 if (content_transform_) { |
| 248 // TODO(jeffbrown): Cache the inverse transform. |
| 249 // Defer matrix multiplications using a matrix stack. |
| 250 SkMatrix inverse_transform; |
| 251 if (!content_transform_.To<SkMatrix>().invert(&inverse_transform)) { |
| 252 // Matrix is singular! |
| 253 // Return [0,0,0][0,0,0][0,0,1] (all zeroes except last component). |
| 254 // This causes all points to be mapped to (0,0) when transformed. |
| 255 inverse_transform.setScale(0.f, 0.f); |
| 256 } |
| 257 inverse_transform.mapXY(parent_point.x(), parent_point.y(), &local_point); |
| 258 global_to_local_transform.preConcat(inverse_transform); |
| 259 } |
| 260 |
| 261 if (content_clip_ && !Contains(content_clip_->To<SkRect>(), local_point)) |
| 262 return false; |
| 263 |
| 264 bool opaque_children = false; |
| 265 if (!hit_test_behavior_ || !hit_test_behavior_->prune) { |
| 266 opaque_children = HitTestInner(content, snapshot, local_point, |
| 267 global_to_local_transform, hits); |
| 268 } |
| 269 |
| 270 return HitTestSelf(content, snapshot, local_point, global_to_local_transform, |
| 271 hits) || |
| 272 opaque_children; |
| 273 } |
| 274 |
| 275 bool NodeDef::HitTestInner( |
| 276 const SceneContent* content, |
| 277 const Snapshot* snapshot, |
| 278 const SkPoint& local_point, |
| 279 const SkMatrix& global_to_local_transform, |
| 280 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
| 281 DCHECK(content); |
| 282 DCHECK(snapshot); |
| 283 DCHECK(hits); |
| 284 |
| 285 // TODO(jeffbrown): Implement a more efficient way to traverse children in |
| 286 // reverse order. |
| 287 std::vector<const NodeDef*> children; |
| 288 TraverseSnapshottedChildren( |
| 289 content, snapshot, [this, &children](const NodeDef* child_node) -> bool { |
| 290 children.push_back(child_node); |
| 291 return true; |
| 292 }); |
| 293 |
| 294 for (auto it = children.crbegin(); it != children.crend(); ++it) { |
| 295 if ((*it)->HitTest(content, snapshot, local_point, |
| 296 global_to_local_transform, hits)) |
| 297 return true; // opaque child covering siblings |
| 298 } |
| 299 return false; |
| 300 } |
| 301 |
| 302 bool NodeDef::HitTestSelf( |
| 303 const SceneContent* content, |
| 304 const Snapshot* snapshot, |
| 305 const SkPoint& local_point, |
| 306 const SkMatrix& global_to_local_transform, |
| 307 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
| 308 DCHECK(content); |
| 309 DCHECK(snapshot); |
| 310 DCHECK(hits); |
| 311 |
| 312 if (!hit_test_behavior_ || |
| 313 hit_test_behavior_->visibility == |
| 314 mojo::gfx::composition::HitTestBehavior::Visibility::INVISIBLE) |
| 315 return false; |
| 316 |
| 317 if (hit_test_behavior_->hit_rect && |
| 318 !Contains(hit_test_behavior_->hit_rect->To<SkRect>(), local_point)) |
| 319 return false; |
| 320 |
| 321 auto hit = mojo::gfx::composition::Hit::New(); |
| 322 hit->set_node(mojo::gfx::composition::NodeHit::New()); |
| 323 hit->get_node()->node_id = node_id_; |
| 324 hit->get_node()->transform = |
| 325 mojo::ConvertTo<mojo::TransformPtr>(global_to_local_transform); |
| 326 hits->push_back(hit.Pass()); |
| 327 return hit_test_behavior_->visibility == |
| 328 mojo::gfx::composition::HitTestBehavior::Visibility::OPAQUE; |
| 329 } |
| 330 |
| 331 RectNodeDef::RectNodeDef( |
| 332 uint32_t node_id, |
| 333 mojo::TransformPtr content_transform, |
| 334 mojo::RectPtr content_clip, |
| 335 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
| 336 Combinator combinator, |
| 337 const std::vector<uint32_t>& child_node_ids, |
| 338 const mojo::Rect& content_rect, |
| 339 const mojo::gfx::composition::Color& color) |
232 : NodeDef(node_id, | 340 : NodeDef(node_id, |
233 content_transform.Pass(), | 341 content_transform.Pass(), |
234 content_clip.Pass(), | 342 content_clip.Pass(), |
| 343 hit_test_behavior.Pass(), |
235 combinator, | 344 combinator, |
236 child_node_ids), | 345 child_node_ids), |
237 content_rect_(content_rect), | 346 content_rect_(content_rect), |
238 color_(color) {} | 347 color_(color) {} |
239 | 348 |
240 RectNodeDef::~RectNodeDef() {} | 349 RectNodeDef::~RectNodeDef() {} |
241 | 350 |
242 void RectNodeDef::RecordPictureInner(const SceneContent* content, | 351 void RectNodeDef::RecordPictureInner(const SceneContent* content, |
243 const Snapshot* snapshot, | 352 const Snapshot* snapshot, |
244 SkCanvas* canvas) const { | 353 SkCanvas* canvas) const { |
245 DCHECK(content); | 354 DCHECK(content); |
246 DCHECK(snapshot); | 355 DCHECK(snapshot); |
247 DCHECK(canvas); | 356 DCHECK(canvas); |
248 | 357 |
249 SkPaint paint; | 358 SkPaint paint; |
250 paint.setColor(MakeSkColor(color_)); | 359 paint.setColor(MakeSkColor(color_)); |
251 canvas->drawRect(content_rect_.To<SkRect>(), paint); | 360 canvas->drawRect(content_rect_.To<SkRect>(), paint); |
252 | 361 |
253 NodeDef::RecordPictureInner(content, snapshot, canvas); | 362 NodeDef::RecordPictureInner(content, snapshot, canvas); |
254 } | 363 } |
255 | 364 |
256 ImageNodeDef::ImageNodeDef(uint32_t node_id, | 365 ImageNodeDef::ImageNodeDef( |
257 mojo::TransformPtr content_transform, | 366 uint32_t node_id, |
258 mojo::RectPtr content_clip, | 367 mojo::TransformPtr content_transform, |
259 Combinator combinator, | 368 mojo::RectPtr content_clip, |
260 const std::vector<uint32_t>& child_node_ids, | 369 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
261 const mojo::Rect& content_rect, | 370 Combinator combinator, |
262 mojo::RectPtr image_rect, | 371 const std::vector<uint32_t>& child_node_ids, |
263 uint32 image_resource_id, | 372 const mojo::Rect& content_rect, |
264 mojo::gfx::composition::BlendPtr blend) | 373 mojo::RectPtr image_rect, |
| 374 uint32 image_resource_id, |
| 375 mojo::gfx::composition::BlendPtr blend) |
265 : NodeDef(node_id, | 376 : NodeDef(node_id, |
266 content_transform.Pass(), | 377 content_transform.Pass(), |
267 content_clip.Pass(), | 378 content_clip.Pass(), |
| 379 hit_test_behavior.Pass(), |
268 combinator, | 380 combinator, |
269 child_node_ids), | 381 child_node_ids), |
270 content_rect_(content_rect), | 382 content_rect_(content_rect), |
271 image_rect_(image_rect.Pass()), | 383 image_rect_(image_rect.Pass()), |
272 image_resource_id_(image_resource_id), | 384 image_resource_id_(image_resource_id), |
273 blend_(blend.Pass()) {} | 385 blend_(blend.Pass()) {} |
274 | 386 |
275 ImageNodeDef::~ImageNodeDef() {} | 387 ImageNodeDef::~ImageNodeDef() {} |
276 | 388 |
277 bool ImageNodeDef::RecordContent(SceneContentBuilder* builder) const { | 389 bool ImageNodeDef::RecordContent(SceneContentBuilder* builder) const { |
(...skipping 21 matching lines...) Expand all Loading... |
299 canvas->drawImageRect(image_resource->image()->image().get(), | 411 canvas->drawImageRect(image_resource->image()->image().get(), |
300 image_rect_ | 412 image_rect_ |
301 ? image_rect_->To<SkRect>() | 413 ? image_rect_->To<SkRect>() |
302 : SkRect::MakeWH(image_resource->image()->width(), | 414 : SkRect::MakeWH(image_resource->image()->width(), |
303 image_resource->image()->height()), | 415 image_resource->image()->height()), |
304 content_rect_.To<SkRect>(), &paint); | 416 content_rect_.To<SkRect>(), &paint); |
305 | 417 |
306 NodeDef::RecordPictureInner(content, snapshot, canvas); | 418 NodeDef::RecordPictureInner(content, snapshot, canvas); |
307 } | 419 } |
308 | 420 |
309 SceneNodeDef::SceneNodeDef(uint32_t node_id, | 421 SceneNodeDef::SceneNodeDef( |
310 mojo::TransformPtr content_transform, | 422 uint32_t node_id, |
311 mojo::RectPtr content_clip, | 423 mojo::TransformPtr content_transform, |
312 Combinator combinator, | 424 mojo::RectPtr content_clip, |
313 const std::vector<uint32_t>& child_node_ids, | 425 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
314 uint32_t scene_resource_id, | 426 Combinator combinator, |
315 uint32_t scene_version) | 427 const std::vector<uint32_t>& child_node_ids, |
| 428 uint32_t scene_resource_id, |
| 429 uint32_t scene_version) |
316 : NodeDef(node_id, | 430 : NodeDef(node_id, |
317 content_transform.Pass(), | 431 content_transform.Pass(), |
318 content_clip.Pass(), | 432 content_clip.Pass(), |
| 433 hit_test_behavior.Pass(), |
319 combinator, | 434 combinator, |
320 child_node_ids), | 435 child_node_ids), |
321 scene_resource_id_(scene_resource_id), | 436 scene_resource_id_(scene_resource_id), |
322 scene_version_(scene_version) {} | 437 scene_version_(scene_version) {} |
323 | 438 |
324 SceneNodeDef::~SceneNodeDef() {} | 439 SceneNodeDef::~SceneNodeDef() {} |
325 | 440 |
326 bool SceneNodeDef::RecordContent(SceneContentBuilder* builder) const { | 441 bool SceneNodeDef::RecordContent(SceneContentBuilder* builder) const { |
327 DCHECK(builder); | 442 DCHECK(builder); |
328 | 443 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 void SceneNodeDef::RecordPictureInner(const SceneContent* content, | 476 void SceneNodeDef::RecordPictureInner(const SceneContent* content, |
362 const Snapshot* snapshot, | 477 const Snapshot* snapshot, |
363 SkCanvas* canvas) const { | 478 SkCanvas* canvas) const { |
364 DCHECK(content); | 479 DCHECK(content); |
365 DCHECK(snapshot); | 480 DCHECK(snapshot); |
366 DCHECK(canvas); | 481 DCHECK(canvas); |
367 | 482 |
368 const SceneContent* resolved_content = | 483 const SceneContent* resolved_content = |
369 snapshot->GetResolvedSceneContent(this); | 484 snapshot->GetResolvedSceneContent(this); |
370 DCHECK(resolved_content); | 485 DCHECK(resolved_content); |
| 486 resolved_content->RecordPicture(snapshot, canvas); |
| 487 |
| 488 NodeDef::RecordPictureInner(content, snapshot, canvas); |
| 489 } |
| 490 |
| 491 bool SceneNodeDef::HitTestInner( |
| 492 const SceneContent* content, |
| 493 const Snapshot* snapshot, |
| 494 const SkPoint& local_point, |
| 495 const SkMatrix& global_to_local_transform, |
| 496 mojo::Array<mojo::gfx::composition::HitPtr>* hits) const { |
| 497 DCHECK(content); |
| 498 DCHECK(snapshot); |
| 499 DCHECK(hits); |
| 500 |
| 501 if (NodeDef::HitTestInner(content, snapshot, local_point, |
| 502 global_to_local_transform, hits)) |
| 503 return true; // opaque child covering referenced scene |
| 504 |
| 505 const SceneContent* resolved_content = |
| 506 snapshot->GetResolvedSceneContent(this); |
| 507 DCHECK(resolved_content); |
371 | 508 |
372 const NodeDef* root_node = resolved_content->GetRootNodeIfExists(); | 509 mojo::gfx::composition::SceneHitPtr scene_hit; |
373 DCHECK(root_node); // must have a root otherwise would have been blocked | 510 bool opaque = resolved_content->HitTest( |
374 root_node->RecordPicture(resolved_content, snapshot, canvas); | 511 snapshot, local_point, global_to_local_transform, &scene_hit); |
375 | 512 if (scene_hit) { |
376 NodeDef::RecordPictureInner(content, snapshot, canvas); | 513 auto hit = mojo::gfx::composition::Hit::New(); |
| 514 hit->set_scene(scene_hit.Pass()); |
| 515 hits->push_back(hit.Pass()); |
| 516 } |
| 517 return opaque; |
377 } | 518 } |
378 | 519 |
379 LayerNodeDef::LayerNodeDef(uint32_t node_id, | 520 LayerNodeDef::LayerNodeDef( |
380 mojo::TransformPtr content_transform, | 521 uint32_t node_id, |
381 mojo::RectPtr content_clip, | 522 mojo::TransformPtr content_transform, |
382 Combinator combinator, | 523 mojo::RectPtr content_clip, |
383 const std::vector<uint32_t>& child_node_ids, | 524 mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior, |
384 const mojo::Size& size, | 525 Combinator combinator, |
385 mojo::gfx::composition::BlendPtr blend) | 526 const std::vector<uint32_t>& child_node_ids, |
| 527 const mojo::Size& size, |
| 528 mojo::gfx::composition::BlendPtr blend) |
386 : NodeDef(node_id, | 529 : NodeDef(node_id, |
387 content_transform.Pass(), | 530 content_transform.Pass(), |
388 content_clip.Pass(), | 531 content_clip.Pass(), |
| 532 hit_test_behavior.Pass(), |
389 combinator, | 533 combinator, |
390 child_node_ids), | 534 child_node_ids), |
391 size_(size), | 535 size_(size), |
392 blend_(blend.Pass()) {} | 536 blend_(blend.Pass()) {} |
393 | 537 |
394 LayerNodeDef::~LayerNodeDef() {} | 538 LayerNodeDef::~LayerNodeDef() {} |
395 | 539 |
396 void LayerNodeDef::RecordPictureInner(const SceneContent* content, | 540 void LayerNodeDef::RecordPictureInner(const SceneContent* content, |
397 const Snapshot* snapshot, | 541 const Snapshot* snapshot, |
398 SkCanvas* canvas) const { | 542 SkCanvas* canvas) const { |
399 DCHECK(content); | 543 DCHECK(content); |
400 DCHECK(snapshot); | 544 DCHECK(snapshot); |
401 DCHECK(canvas); | 545 DCHECK(canvas); |
402 | 546 |
403 SkPaint paint; | 547 SkPaint paint; |
404 SetPaintForBlend(&paint, blend_.get()); | 548 SetPaintForBlend(&paint, blend_.get()); |
405 | 549 |
406 canvas->saveLayer(SkRect::MakeWH(size_.width, size_.height), &paint); | 550 canvas->saveLayer(SkRect::MakeWH(size_.width, size_.height), &paint); |
407 NodeDef::RecordPictureInner(content, snapshot, canvas); | 551 NodeDef::RecordPictureInner(content, snapshot, canvas); |
408 canvas->restore(); | 552 canvas->restore(); |
409 } | 553 } |
410 | 554 |
411 } // namespace compositor | 555 } // namespace compositor |
OLD | NEW |