OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/surfaces/surface_aggregator.h" | 5 #include "cc/surfaces/surface_aggregator.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 aggregate_only_damaged_(aggregate_only_damaged) { | 51 aggregate_only_damaged_(aggregate_only_damaged) { |
52 DCHECK(manager_); | 52 DCHECK(manager_); |
53 } | 53 } |
54 | 54 |
55 SurfaceAggregator::~SurfaceAggregator() { | 55 SurfaceAggregator::~SurfaceAggregator() { |
56 // Notify client of all surfaces being removed. | 56 // Notify client of all surfaces being removed. |
57 contained_surfaces_.clear(); | 57 contained_surfaces_.clear(); |
58 ProcessAddedAndRemovedSurfaces(); | 58 ProcessAddedAndRemovedSurfaces(); |
59 } | 59 } |
60 | 60 |
61 SurfaceAggregator::PrewalkResult::PrewalkResult() {} | |
62 | |
63 SurfaceAggregator::PrewalkResult::~PrewalkResult() {} | |
64 | |
65 // Create a clip rect for an aggregated quad from the original clip rect and | 61 // Create a clip rect for an aggregated quad from the original clip rect and |
66 // the clip rect from the surface it's on. | 62 // the clip rect from the surface it's on. |
67 SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect( | 63 SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect( |
68 const ClipData& surface_clip, | 64 const ClipData& surface_clip, |
69 const ClipData& quad_clip, | 65 const ClipData& quad_clip, |
70 const gfx::Transform& target_transform) { | 66 const gfx::Transform& target_transform) { |
71 ClipData out_clip; | 67 ClipData out_clip; |
72 if (surface_clip.is_clipped) | 68 if (surface_clip.is_clipped) |
73 out_clip = surface_clip; | 69 out_clip = surface_clip; |
74 | 70 |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 Surface* surface_ptr = manager_->GetSurfaceForId(surface.first); | 484 Surface* surface_ptr = manager_->GetSurfaceForId(surface.first); |
489 if (surface_ptr) | 485 if (surface_ptr) |
490 client_->AddSurface(surface_ptr); | 486 client_->AddSurface(surface_ptr); |
491 } | 487 } |
492 } | 488 } |
493 } | 489 } |
494 | 490 |
495 // Walk the Surface tree from surface_id. Validate the resources of the current | 491 // Walk the Surface tree from surface_id. Validate the resources of the current |
496 // surface and its descendants, check if there are any copy requests, and | 492 // surface and its descendants, check if there are any copy requests, and |
497 // return the combined damage rect. | 493 // return the combined damage rect. |
498 gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id, | 494 gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id) { |
499 PrewalkResult* result) { | |
500 if (referenced_surfaces_.count(surface_id)) | 495 if (referenced_surfaces_.count(surface_id)) |
501 return gfx::Rect(); | 496 return gfx::Rect(); |
502 Surface* surface = manager_->GetSurfaceForId(surface_id); | 497 Surface* surface = manager_->GetSurfaceForId(surface_id); |
503 if (!surface) { | 498 if (!surface) { |
504 contained_surfaces_[surface_id] = 0; | 499 contained_surfaces_[surface_id] = 0; |
505 return gfx::Rect(); | 500 return gfx::Rect(); |
506 } | 501 } |
507 contained_surfaces_[surface_id] = surface->frame_index(); | 502 contained_surfaces_[surface_id] = surface->frame_index(); |
508 const CompositorFrame* surface_frame = surface->GetEligibleFrame(); | 503 const CompositorFrame* surface_frame = surface->GetEligibleFrame(); |
509 if (!surface_frame) | 504 if (!surface_frame) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 } | 562 } |
568 | 563 |
569 if (invalid_frame) | 564 if (invalid_frame) |
570 return gfx::Rect(); | 565 return gfx::Rect(); |
571 valid_surfaces_.insert(surface->surface_id()); | 566 valid_surfaces_.insert(surface->surface_id()); |
572 | 567 |
573 if (provider_) | 568 if (provider_) |
574 provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources); | 569 provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources); |
575 | 570 |
576 for (const auto& render_pass : frame_data->render_pass_list) | 571 for (const auto& render_pass : frame_data->render_pass_list) |
577 result->has_copy_requests |= !render_pass->copy_requests.empty(); | 572 has_copy_requests_ |= !render_pass->copy_requests.empty(); |
578 | 573 |
579 gfx::Rect damage_rect; | 574 gfx::Rect damage_rect; |
580 if (!frame_data->render_pass_list.empty()) { | 575 if (!frame_data->render_pass_list.empty()) { |
581 RenderPass* last_pass = frame_data->render_pass_list.back().get(); | 576 RenderPass* last_pass = frame_data->render_pass_list.back().get(); |
582 damage_rect = | 577 damage_rect = |
583 DamageRectForSurface(surface, *last_pass, last_pass->output_rect); | 578 DamageRectForSurface(surface, *last_pass, last_pass->output_rect); |
584 } | 579 } |
585 | 580 |
586 // Avoid infinite recursion by adding current surface to | 581 // Avoid infinite recursion by adding current surface to |
587 // referenced_surfaces_. | 582 // referenced_surfaces_. |
588 SurfaceSet::iterator it = | 583 SurfaceSet::iterator it = |
589 referenced_surfaces_.insert(surface->surface_id()).first; | 584 referenced_surfaces_.insert(surface->surface_id()).first; |
590 for (const auto& surface_info : child_surfaces) { | 585 for (const auto& surface_info : child_surfaces) { |
591 gfx::Rect surface_damage = PrewalkTree(surface_info.first, result); | 586 gfx::Rect surface_damage = PrewalkTree(surface_info.first); |
592 damage_rect.Union( | 587 damage_rect.Union( |
593 MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage)); | 588 MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage)); |
594 } | 589 } |
595 | |
596 for (const auto& surface_id : surface_frame->metadata.referenced_surfaces) { | |
597 if (!contained_surfaces_.count(surface_id)) { | |
598 result->undrawn_surfaces.insert(surface_id); | |
599 PrewalkTree(surface_id, result); | |
600 } | |
601 } | |
602 | |
603 referenced_surfaces_.erase(it); | 590 referenced_surfaces_.erase(it); |
604 return damage_rect; | 591 return damage_rect; |
605 } | 592 } |
606 | 593 |
607 void SurfaceAggregator::CopyUndrawnSurfaces(PrewalkResult* prewalk_result) { | |
608 // undrawn_surfaces are Surfaces that were identified by prewalk as being | |
609 // referenced by a drawn Surface, but aren't contained in a SurfaceDrawQuad. | |
610 // They need to be iterated over to ensure that any copy requests on them | |
611 // (or on Surfaces they reference) are executed. | |
612 std::vector<SurfaceId> surfaces_to_copy( | |
613 prewalk_result->undrawn_surfaces.begin(), | |
614 prewalk_result->undrawn_surfaces.end()); | |
615 | |
616 for (size_t i = 0; i < surfaces_to_copy.size(); i++) { | |
617 SurfaceId surface_id = surfaces_to_copy[i]; | |
618 Surface* surface = manager_->GetSurfaceForId(surface_id); | |
619 const CompositorFrame* surface_frame = surface->GetEligibleFrame(); | |
620 if (!surface_frame) | |
621 continue; | |
622 bool surface_has_copy_requests = false; | |
623 for (const auto& render_pass : | |
624 surface_frame->delegated_frame_data->render_pass_list) { | |
625 surface_has_copy_requests |= !render_pass->copy_requests.empty(); | |
626 } | |
627 if (!surface_has_copy_requests) { | |
628 // Children are not necessarily included in undrawn_surfaces (because | |
629 // they weren't referenced directly from a drawn surface), but may have | |
630 // copy requests, so make sure to check them as well. | |
631 for (const auto& child_id : surface_frame->metadata.referenced_surfaces) { | |
632 // Don't iterate over the child Surface if it was already listed as a | |
633 // child of a different Surface, or in the case where there's infinite | |
634 // recursion. | |
635 if (!prewalk_result->undrawn_surfaces.count(child_id)) { | |
636 surfaces_to_copy.push_back(child_id); | |
637 prewalk_result->undrawn_surfaces.insert(child_id); | |
638 } | |
639 } | |
640 } else { | |
641 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; | |
642 CopyPasses(surface_frame->delegated_frame_data.get(), surface); | |
643 referenced_surfaces_.erase(it); | |
644 } | |
645 } | |
646 } | |
647 | |
648 scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) { | 594 scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) { |
649 Surface* surface = manager_->GetSurfaceForId(surface_id); | 595 Surface* surface = manager_->GetSurfaceForId(surface_id); |
650 DCHECK(surface); | 596 DCHECK(surface); |
651 contained_surfaces_[surface_id] = surface->frame_index(); | 597 contained_surfaces_[surface_id] = surface->frame_index(); |
652 const CompositorFrame* root_surface_frame = surface->GetEligibleFrame(); | 598 const CompositorFrame* root_surface_frame = surface->GetEligibleFrame(); |
653 if (!root_surface_frame) | 599 if (!root_surface_frame) |
654 return nullptr; | 600 return nullptr; |
655 TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate"); | 601 TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate"); |
656 | 602 |
657 scoped_ptr<CompositorFrame> frame(new CompositorFrame); | 603 scoped_ptr<CompositorFrame> frame(new CompositorFrame); |
658 frame->delegated_frame_data = make_scoped_ptr(new DelegatedFrameData); | 604 frame->delegated_frame_data = make_scoped_ptr(new DelegatedFrameData); |
659 | 605 |
660 DCHECK(root_surface_frame->delegated_frame_data); | 606 DCHECK(root_surface_frame->delegated_frame_data); |
661 | 607 |
662 dest_resource_list_ = &frame->delegated_frame_data->resource_list; | 608 dest_resource_list_ = &frame->delegated_frame_data->resource_list; |
663 dest_pass_list_ = &frame->delegated_frame_data->render_pass_list; | 609 dest_pass_list_ = &frame->delegated_frame_data->render_pass_list; |
664 | 610 |
665 valid_surfaces_.clear(); | 611 valid_surfaces_.clear(); |
666 PrewalkResult prewalk_result; | 612 has_copy_requests_ = false; |
667 root_damage_rect_ = PrewalkTree(surface_id, &prewalk_result); | 613 root_damage_rect_ = PrewalkTree(surface_id); |
668 has_copy_requests_ = prewalk_result.has_copy_requests; | |
669 | 614 |
670 CopyUndrawnSurfaces(&prewalk_result); | |
671 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; | 615 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; |
672 CopyPasses(root_surface_frame->delegated_frame_data.get(), surface); | 616 CopyPasses(root_surface_frame->delegated_frame_data.get(), surface); |
673 referenced_surfaces_.erase(it); | 617 referenced_surfaces_.erase(it); |
674 | 618 |
675 DCHECK(referenced_surfaces_.empty()); | 619 DCHECK(referenced_surfaces_.empty()); |
676 | 620 |
677 if (dest_pass_list_->empty()) | 621 if (dest_pass_list_->empty()) |
678 return nullptr; | 622 return nullptr; |
679 dest_pass_list_->back()->damage_rect = root_damage_rect_; | 623 dest_pass_list_->back()->damage_rect = root_damage_rect_; |
680 | 624 |
(...skipping 27 matching lines...) Expand all Loading... |
708 | 652 |
709 void SurfaceAggregator::SetFullDamageForSurface(SurfaceId surface_id) { | 653 void SurfaceAggregator::SetFullDamageForSurface(SurfaceId surface_id) { |
710 auto it = previous_contained_surfaces_.find(surface_id); | 654 auto it = previous_contained_surfaces_.find(surface_id); |
711 if (it == previous_contained_surfaces_.end()) | 655 if (it == previous_contained_surfaces_.end()) |
712 return; | 656 return; |
713 // Set the last drawn index as 0 to ensure full damage next time it's drawn. | 657 // Set the last drawn index as 0 to ensure full damage next time it's drawn. |
714 it->second = 0; | 658 it->second = 0; |
715 } | 659 } |
716 | 660 |
717 } // namespace cc | 661 } // namespace cc |
OLD | NEW |