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/layers/layer.h" | 10 #include "cc/layers/layer.h" |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( | 328 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( |
329 stack_[last_index].occlusion_from_outside_target, | 329 stack_[last_index].occlusion_from_outside_target, |
330 false, | 330 false, |
331 gfx::Rect(), | 331 gfx::Rect(), |
332 old_surface->draw_transform()); | 332 old_surface->draw_transform()); |
333 | 333 |
334 gfx::Rect unoccluded_surface_rect; | 334 gfx::Rect unoccluded_surface_rect; |
335 gfx::Rect unoccluded_replica_rect; | 335 gfx::Rect unoccluded_replica_rect; |
336 if (old_target->background_filters().HasFilterThatMovesPixels()) { | 336 if (old_target->background_filters().HasFilterThatMovesPixels()) { |
337 unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect( | 337 unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect( |
338 old_target, false, old_surface->content_rect()); | 338 old_target, old_surface->content_rect(), old_surface->draw_transform()); |
339 if (old_target->has_replica()) { | 339 if (old_target->has_replica()) { |
340 unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect( | 340 unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect( |
341 old_target, true, old_surface->content_rect()); | 341 old_target, |
| 342 old_surface->content_rect(), |
| 343 old_surface->replica_draw_transform()); |
342 } | 344 } |
343 } | 345 } |
344 | 346 |
345 if (surface_will_be_at_top_after_pop) { | 347 if (surface_will_be_at_top_after_pop) { |
346 // Merge the top of the stack down. | 348 // Merge the top of the stack down. |
347 stack_[last_index - 1].occlusion_from_inside_target.Union( | 349 stack_[last_index - 1].occlusion_from_inside_target.Union( |
348 old_occlusion_from_inside_target_in_new_target); | 350 old_occlusion_from_inside_target_in_new_target); |
349 // TODO(danakj): Strictly this should subtract the inside target occlusion | 351 // TODO(danakj): Strictly this should subtract the inside target occlusion |
350 // before union. | 352 // before union. |
351 if (new_target->parent()) { | 353 if (new_target->parent()) { |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( | 586 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( |
585 inverse_draw_transform, unoccluded_rect_in_target_surface); | 587 inverse_draw_transform, unoccluded_rect_in_target_surface); |
586 unoccluded_rect.Intersect(content_rect); | 588 unoccluded_rect.Intersect(content_rect); |
587 | 589 |
588 return unoccluded_rect; | 590 return unoccluded_rect; |
589 } | 591 } |
590 | 592 |
591 template <typename LayerType> | 593 template <typename LayerType> |
592 gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( | 594 gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( |
593 const LayerType* layer, | 595 const LayerType* layer, |
594 bool for_replica, | 596 const gfx::Rect& content_rect, |
595 const gfx::Rect& content_rect) const { | 597 const gfx::Transform& draw_transform) const { |
596 DCHECK(!stack_.empty()); | 598 DCHECK(!stack_.empty()); |
597 // The layer is a contributing render_target so it should have a surface. | 599 // The layer is a contributing render_target so it should have a surface. |
598 DCHECK(layer->render_surface()); | 600 DCHECK(layer->render_surface()); |
599 // The layer is a contributing render_target so its target should be itself. | 601 // The layer is a contributing render_target so its target should be itself. |
600 DCHECK_EQ(layer->render_target(), layer); | 602 DCHECK_EQ(layer->render_target(), layer); |
601 // The layer should not be the root, else what is is contributing to? | 603 // The layer should not be the root, else what is is contributing to? |
602 DCHECK(layer->parent()); | 604 DCHECK(layer->parent()); |
603 // This should be called while the layer is still considered the current | 605 // This should be called while the layer is still considered the current |
604 // target in the occlusion tracker. | 606 // target in the occlusion tracker. |
605 DCHECK_EQ(layer, stack_.back().target); | 607 DCHECK_EQ(layer, stack_.back().target); |
606 | 608 |
607 if (content_rect.IsEmpty()) | 609 if (content_rect.IsEmpty()) |
608 return content_rect; | 610 return content_rect; |
609 | 611 |
610 const typename LayerType::RenderSurfaceType* surface = | |
611 layer->render_surface(); | |
612 const LayerType* contributing_surface_render_target = | |
613 layer->parent()->render_target(); | |
614 | |
615 if (!SurfaceTransformsToTargetKnown(surface)) | |
616 return content_rect; | |
617 | |
618 gfx::Transform draw_transform = | |
619 for_replica ? surface->replica_draw_transform() | |
620 : surface->draw_transform(); | |
621 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | |
622 if (!draw_transform.GetInverse(&inverse_draw_transform)) | |
623 return content_rect; | |
624 | |
625 // A contributing surface doesn't get occluded by things inside its own | 612 // A contributing surface doesn't get occluded by things inside its own |
626 // surface, so only things outside the surface can occlude it. That occlusion | 613 // surface, so only things outside the surface can occlude it. That occlusion |
627 // is found just below the top of the stack (if it exists). | 614 // is found just below the top of the stack (if it exists). |
628 bool has_occlusion = stack_.size() > 1; | 615 bool has_occlusion = stack_.size() > 1; |
| 616 if (!has_occlusion) |
| 617 return content_rect; |
| 618 |
| 619 const StackObject& second_last = stack_[stack_.size() - 2]; |
| 620 |
| 621 if (second_last.occlusion_from_inside_target.IsEmpty() && |
| 622 second_last.occlusion_from_outside_target.IsEmpty()) |
| 623 return content_rect; |
| 624 |
| 625 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 626 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 627 return content_rect; |
629 | 628 |
630 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 629 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
631 // partial pixels in the resulting Rect. | 630 // partial pixels in the resulting Rect. |
632 Region unoccluded_region_in_target_surface = | 631 Region unoccluded_region_in_target_surface = |
633 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 632 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
634 // Layers can't clip across surfaces, so count this as internal occlusion. | 633 unoccluded_region_in_target_surface.Subtract( |
635 if (surface->is_clipped()) | 634 second_last.occlusion_from_inside_target); |
636 unoccluded_region_in_target_surface.Intersect(surface->clip_rect()); | 635 unoccluded_region_in_target_surface.Subtract( |
637 if (has_occlusion) { | 636 second_last.occlusion_from_outside_target); |
638 const StackObject& second_last = stack_[stack_.size() - 2]; | |
639 unoccluded_region_in_target_surface.Subtract( | |
640 second_last.occlusion_from_inside_target); | |
641 unoccluded_region_in_target_surface.Subtract( | |
642 second_last.occlusion_from_outside_target); | |
643 } | |
644 | |
645 // Treat other clipping as occlusion from outside the target surface. | |
646 unoccluded_region_in_target_surface.Intersect( | |
647 contributing_surface_render_target->render_surface()->content_rect()); | |
648 unoccluded_region_in_target_surface.Intersect( | |
649 ScreenSpaceClipRectInTargetSurface( | |
650 contributing_surface_render_target->render_surface(), | |
651 screen_space_clip_rect_)); | |
652 | 637 |
653 gfx::Rect unoccluded_rect_in_target_surface = | 638 gfx::Rect unoccluded_rect_in_target_surface = |
654 unoccluded_region_in_target_surface.bounds(); | 639 unoccluded_region_in_target_surface.bounds(); |
655 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( | 640 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( |
656 inverse_draw_transform, unoccluded_rect_in_target_surface); | 641 inverse_draw_transform, unoccluded_rect_in_target_surface); |
657 unoccluded_rect.Intersect(content_rect); | 642 unoccluded_rect.Intersect(content_rect); |
658 | 643 |
659 return unoccluded_rect; | 644 return unoccluded_rect; |
660 } | 645 } |
661 | 646 |
662 // Instantiate (and export) templates here for the linker. | 647 // Instantiate (and export) templates here for the linker. |
663 template class OcclusionTracker<Layer>; | 648 template class OcclusionTracker<Layer>; |
664 template class OcclusionTracker<LayerImpl>; | 649 template class OcclusionTracker<LayerImpl>; |
665 | 650 |
666 } // namespace cc | 651 } // namespace cc |
OLD | NEW |