| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "cc/trees/occlusion_tracker.h" | 5 #include "cc/trees/occlusion_tracker.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "cc/base/math_util.h" | 9 #include "cc/base/math_util.h" |
| 10 #include "cc/base/region.h" | 10 #include "cc/base/region.h" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // Verify that rects within the |surface| will remain rects in its target | 77 // Verify that rects within the |surface| will remain rects in its target |
| 78 // surface after applying |transform|. If this is true, then apply |transform| | 78 // surface after applying |transform|. If this is true, then apply |transform| |
| 79 // to each rect within |region| in order to transform the entire Region. | 79 // to each rect within |region| in order to transform the entire Region. |
| 80 | 80 |
| 81 // TODO(danakj): Find a rect interior to each transformed quad. | 81 // TODO(danakj): Find a rect interior to each transformed quad. |
| 82 if (!transform.Preserves2dAxisAlignment()) | 82 if (!transform.Preserves2dAxisAlignment()) |
| 83 return SimpleEnclosedRegion(); | 83 return SimpleEnclosedRegion(); |
| 84 | 84 |
| 85 SimpleEnclosedRegion transformed_region; | 85 SimpleEnclosedRegion transformed_region; |
| 86 for (size_t i = 0; i < region.GetRegionComplexity(); ++i) { | 86 for (size_t i = 0; i < region.GetRegionComplexity(); ++i) { |
| 87 bool clipped; | 87 // NonClippedRect is okay because we checked Preserves2dAxisAlignment above. |
| 88 gfx::QuadF transformed_quad = | |
| 89 MathUtil::MapQuad(transform, gfx::QuadF(region.GetRect(i)), &clipped); | |
| 90 gfx::Rect transformed_rect = | 88 gfx::Rect transformed_rect = |
| 91 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); | 89 MathUtil::MapEnclosedNonClippedRect(transform, region.GetRect(i)); |
| 92 DCHECK(!clipped); // We only map if the transform preserves axis alignment. | |
| 93 if (have_clip_rect) | 90 if (have_clip_rect) |
| 94 transformed_rect.Intersect(clip_rect_in_new_target); | 91 transformed_rect.Intersect(clip_rect_in_new_target); |
| 95 transformed_region.Union(transformed_rect); | 92 transformed_region.Union(transformed_rect); |
| 96 } | 93 } |
| 97 return transformed_region; | 94 return transformed_region; |
| 98 } | 95 } |
| 99 | 96 |
| 100 static inline bool LayerOpacityKnown(const Layer* layer) { | 97 static inline bool LayerOpacityKnown(const Layer* layer) { |
| 101 return !layer->draw_opacity_is_animating(); | 98 return !layer->draw_opacity_is_animating(); |
| 102 } | 99 } |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface( | 422 gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface( |
| 426 layer->render_target()->render_surface(), screen_space_clip_rect_); | 423 layer->render_target()->render_surface(), screen_space_clip_rect_); |
| 427 if (layer->is_clipped()) { | 424 if (layer->is_clipped()) { |
| 428 clip_rect_in_target.Intersect(layer->clip_rect()); | 425 clip_rect_in_target.Intersect(layer->clip_rect()); |
| 429 } else { | 426 } else { |
| 430 clip_rect_in_target.Intersect( | 427 clip_rect_in_target.Intersect( |
| 431 layer->render_target()->render_surface()->content_rect()); | 428 layer->render_target()->render_surface()->content_rect()); |
| 432 } | 429 } |
| 433 | 430 |
| 434 for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) { | 431 for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) { |
| 435 bool clipped; | 432 // NonClippedRect is okay because we checked Preserves2dAxisAlignment above. |
| 436 gfx::QuadF transformed_quad = | 433 gfx::Rect transformed_rect = MathUtil::MapEnclosedNonClippedRect( |
| 437 MathUtil::MapQuad(layer->draw_transform(), | 434 layer->draw_transform(), opaque_contents.GetRect(i)); |
| 438 gfx::QuadF(opaque_contents.GetRect(i)), | |
| 439 &clipped); | |
| 440 gfx::Rect transformed_rect = | |
| 441 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); | |
| 442 DCHECK(!clipped); // We only map if the transform preserves axis alignment. | |
| 443 transformed_rect.Intersect(clip_rect_in_target); | 435 transformed_rect.Intersect(clip_rect_in_target); |
| 444 if (transformed_rect.width() < minimum_tracking_size_.width() && | 436 if (transformed_rect.width() < minimum_tracking_size_.width() && |
| 445 transformed_rect.height() < minimum_tracking_size_.height()) | 437 transformed_rect.height() < minimum_tracking_size_.height()) |
| 446 continue; | 438 continue; |
| 447 stack_.back().occlusion_from_inside_target.Union(transformed_rect); | 439 stack_.back().occlusion_from_inside_target.Union(transformed_rect); |
| 448 | 440 |
| 449 if (!occluding_screen_space_rects_) | 441 if (!occluding_screen_space_rects_) |
| 450 continue; | 442 continue; |
| 451 | 443 |
| 452 // Save the occluding area in screen space for debug visualization. | 444 // Save the occluding area in screen space for debug visualization. |
| 453 gfx::QuadF screen_space_quad = MathUtil::MapQuad( | 445 gfx::Rect screen_space_rect = MathUtil::MapEnclosedClippedRect( |
| 454 layer->render_target()->render_surface()->screen_space_transform(), | 446 layer->render_target()->render_surface()->screen_space_transform(), |
| 455 gfx::QuadF(transformed_rect), &clipped); | 447 transformed_rect); |
| 456 // TODO(danakj): Store the quad in the debug info instead of the bounding | |
| 457 // box. | |
| 458 gfx::Rect screen_space_rect = | |
| 459 gfx::ToEnclosedRect(screen_space_quad.BoundingBox()); | |
| 460 occluding_screen_space_rects_->push_back(screen_space_rect); | 448 occluding_screen_space_rects_->push_back(screen_space_rect); |
| 461 } | 449 } |
| 462 | 450 |
| 463 if (!non_occluding_screen_space_rects_) | 451 if (!non_occluding_screen_space_rects_) |
| 464 return; | 452 return; |
| 465 | 453 |
| 466 Region non_opaque_contents(gfx::Rect(layer->content_bounds())); | 454 Region non_opaque_contents(gfx::Rect(layer->content_bounds())); |
| 467 non_opaque_contents.Subtract(opaque_contents); | 455 non_opaque_contents.Subtract(opaque_contents); |
| 468 | 456 |
| 469 for (Region::Iterator non_opaque_content_rects(non_opaque_contents); | 457 for (Region::Iterator non_opaque_content_rects(non_opaque_contents); |
| 470 non_opaque_content_rects.has_rect(); | 458 non_opaque_content_rects.has_rect(); |
| 471 non_opaque_content_rects.next()) { | 459 non_opaque_content_rects.next()) { |
| 472 // We've already checked for clipping in the MapQuad call above, these calls | 460 // NonClippedRect is okay because we checked Preserves2dAxisAlignment above. |
| 473 // should not clip anything further. | 461 gfx::Rect transformed_rect = MathUtil::MapEnclosedNonClippedRect( |
| 474 gfx::Rect transformed_rect = gfx::ToEnclosedRect( | 462 layer->draw_transform(), non_opaque_content_rects.rect()); |
| 475 MathUtil::MapClippedRect(layer->draw_transform(), | |
| 476 gfx::RectF(non_opaque_content_rects.rect()))); | |
| 477 transformed_rect.Intersect(clip_rect_in_target); | 463 transformed_rect.Intersect(clip_rect_in_target); |
| 478 if (transformed_rect.IsEmpty()) | 464 if (transformed_rect.IsEmpty()) |
| 479 continue; | 465 continue; |
| 480 | 466 |
| 481 bool clipped; | 467 gfx::Rect screen_space_rect = MathUtil::MapEnclosedClippedRect( |
| 482 gfx::QuadF screen_space_quad = MathUtil::MapQuad( | |
| 483 layer->render_target()->render_surface()->screen_space_transform(), | 468 layer->render_target()->render_surface()->screen_space_transform(), |
| 484 gfx::QuadF(transformed_rect), | 469 transformed_rect); |
| 485 &clipped); | |
| 486 // TODO(danakj): Store the quad in the debug info instead of the bounding | |
| 487 // box. | |
| 488 gfx::Rect screen_space_rect = | |
| 489 gfx::ToEnclosedRect(screen_space_quad.BoundingBox()); | |
| 490 non_occluding_screen_space_rects_->push_back(screen_space_rect); | 470 non_occluding_screen_space_rects_->push_back(screen_space_rect); |
| 491 } | 471 } |
| 492 } | 472 } |
| 493 | 473 |
| 494 template <typename LayerType> | 474 template <typename LayerType> |
| 495 bool OcclusionTracker<LayerType>::Occluded( | 475 bool OcclusionTracker<LayerType>::Occluded( |
| 496 const LayerType* render_target, | 476 const LayerType* render_target, |
| 497 const gfx::Rect& content_rect, | 477 const gfx::Rect& content_rect, |
| 498 const gfx::Transform& draw_transform) const { | 478 const gfx::Transform& draw_transform) const { |
| 499 DCHECK(!stack_.empty()); | 479 DCHECK(!stack_.empty()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 513 const StackObject& back = stack_.back(); | 493 const StackObject& back = stack_.back(); |
| 514 if (back.occlusion_from_inside_target.IsEmpty() && | 494 if (back.occlusion_from_inside_target.IsEmpty() && |
| 515 back.occlusion_from_outside_target.IsEmpty()) { | 495 back.occlusion_from_outside_target.IsEmpty()) { |
| 516 return false; | 496 return false; |
| 517 } | 497 } |
| 518 | 498 |
| 519 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | 499 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 520 if (!draw_transform.GetInverse(&inverse_draw_transform)) | 500 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 521 return false; | 501 return false; |
| 522 | 502 |
| 523 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 503 // Take the EnclosingRect at each step, as we want to contain any unoccluded |
| 524 // partial pixels in the resulting Rect. | 504 // partial pixels in the resulting Rect. |
| 525 gfx::Rect unoccluded_rect_in_target_surface = | 505 gfx::Rect unoccluded_rect_in_target_surface = |
| 526 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 506 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
| 527 DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); | 507 DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
| 528 DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); | 508 DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); |
| 529 // These subtract operations are more lossy than if we did both operations at | 509 // These subtract operations are more lossy than if we did both operations at |
| 530 // once. | 510 // once. |
| 531 unoccluded_rect_in_target_surface.Subtract( | 511 unoccluded_rect_in_target_surface.Subtract( |
| 532 stack_.back().occlusion_from_inside_target.bounds()); | 512 stack_.back().occlusion_from_inside_target.bounds()); |
| 533 unoccluded_rect_in_target_surface.Subtract( | 513 unoccluded_rect_in_target_surface.Subtract( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 547 const StackObject& back = stack_.back(); | 527 const StackObject& back = stack_.back(); |
| 548 if (back.occlusion_from_inside_target.IsEmpty() && | 528 if (back.occlusion_from_inside_target.IsEmpty() && |
| 549 back.occlusion_from_outside_target.IsEmpty()) { | 529 back.occlusion_from_outside_target.IsEmpty()) { |
| 550 return content_rect; | 530 return content_rect; |
| 551 } | 531 } |
| 552 | 532 |
| 553 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | 533 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 554 if (!draw_transform.GetInverse(&inverse_draw_transform)) | 534 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 555 return content_rect; | 535 return content_rect; |
| 556 | 536 |
| 557 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 537 // Take the EnclosingRect at each step, as we want to contain any unoccluded |
| 558 // partial pixels in the resulting Rect. | 538 // partial pixels in the resulting Rect. |
| 559 gfx::Rect unoccluded_rect_in_target_surface = | 539 gfx::Rect unoccluded_rect_in_target_surface = |
| 560 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 540 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
| 561 DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); | 541 DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
| 562 DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); | 542 DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); |
| 563 // These subtract operations are more lossy than if we did both operations at | 543 // These subtract operations are more lossy than if we did both operations at |
| 564 // once. | 544 // once. |
| 565 unoccluded_rect_in_target_surface.Subtract( | 545 unoccluded_rect_in_target_surface.Subtract( |
| 566 back.occlusion_from_inside_target.bounds()); | 546 back.occlusion_from_inside_target.bounds()); |
| 567 unoccluded_rect_in_target_surface.Subtract( | 547 unoccluded_rect_in_target_surface.Subtract( |
| (...skipping 25 matching lines...) Expand all Loading... |
| 593 | 573 |
| 594 const StackObject& second_last = stack_[stack_.size() - 2]; | 574 const StackObject& second_last = stack_[stack_.size() - 2]; |
| 595 if (second_last.occlusion_from_inside_target.IsEmpty() && | 575 if (second_last.occlusion_from_inside_target.IsEmpty() && |
| 596 second_last.occlusion_from_outside_target.IsEmpty()) | 576 second_last.occlusion_from_outside_target.IsEmpty()) |
| 597 return content_rect; | 577 return content_rect; |
| 598 | 578 |
| 599 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | 579 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 600 if (!draw_transform.GetInverse(&inverse_draw_transform)) | 580 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 601 return content_rect; | 581 return content_rect; |
| 602 | 582 |
| 603 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 583 // Take the EnclosingRect at each step, as we want to contain any unoccluded |
| 604 // partial pixels in the resulting Rect. | 584 // partial pixels in the resulting Rect. |
| 605 gfx::Rect unoccluded_rect_in_target_surface = | 585 gfx::Rect unoccluded_rect_in_target_surface = |
| 606 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 586 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
| 607 DCHECK_LE(second_last.occlusion_from_inside_target.GetRegionComplexity(), 1u); | 587 DCHECK_LE(second_last.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
| 608 DCHECK_LE(second_last.occlusion_from_outside_target.GetRegionComplexity(), | 588 DCHECK_LE(second_last.occlusion_from_outside_target.GetRegionComplexity(), |
| 609 1u); | 589 1u); |
| 610 // These subtract operations are more lossy than if we did both operations at | 590 // These subtract operations are more lossy than if we did both operations at |
| 611 // once. | 591 // once. |
| 612 unoccluded_rect_in_target_surface.Subtract( | 592 unoccluded_rect_in_target_surface.Subtract( |
| 613 second_last.occlusion_from_inside_target.bounds()); | 593 second_last.occlusion_from_inside_target.bounds()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 633 for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i) | 613 for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i) |
| 634 visible_region.Subtract(occluded.GetRect(i)); | 614 visible_region.Subtract(occluded.GetRect(i)); |
| 635 return visible_region; | 615 return visible_region; |
| 636 } | 616 } |
| 637 | 617 |
| 638 // Instantiate (and export) templates here for the linker. | 618 // Instantiate (and export) templates here for the linker. |
| 639 template class OcclusionTracker<Layer>; | 619 template class OcclusionTracker<Layer>; |
| 640 template class OcclusionTracker<LayerImpl>; | 620 template class OcclusionTracker<LayerImpl>; |
| 641 | 621 |
| 642 } // namespace cc | 622 } // namespace cc |
| OLD | NEW |