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